Repository: jfrog/terraform-provider-xray
Pull request #9 (2021-12-11 00:49:23)

Watch v2

github-actions[bot]: ****CLA Assistant Lite bot**** All contributors have signed the CLA  ✍️ 
danielmkn: @chb0github @alexhung  Not sure about all the `nil` comments. I need to have more understanding of how `diags` work. I took it from the Hashi corp example.
danielmkn: @alexhung please check and approve


Patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 242f92b4..afb53fb3 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -3,7 +3,7 @@ name: Bug report
 about: Create a report to help us improve
 title: ''
 labels: bug
-assignees: chb0github
+assignees: danielmkn
 
 ---
 
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 22c66984..3aa0388b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,7 +1,7 @@
 # This GitHub action can publish assets for release when a tag is created.
 # Currently its setup to run on any tag that matches the pattern "v*" (ie. v0.1.0).
 #
-# This uses an action (paultyng/ghaction-import-gpg) that assumes you set your 
+# This uses an action (hashicorp/ghaction-import-gpg) that assumes you set your
 # private key in the `GPG_PRIVATE_KEY` secret and passphrase in the `PASSPHRASE`
 # secret. If you would rather own your own GPG handling, please fork this action
 # or use an alternative one for key handling.
@@ -33,7 +33,7 @@ jobs:
       -
         name: Import GPG key
         id: import_gpg
-        uses: paultyng/ghaction-import-gpg@v2.1.0
+        uses: hashicorp/ghaction-import-gpg@v2.1.0
         env:
           GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
           PASSPHRASE: ${{ secrets.PASSPHRASE }}
diff --git a/GNUmakefile b/GNUmakefile
index 4b20336b..62d3e26a 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,32 +1,35 @@
 TEST?=./...
 PKG_NAME=pkg/xray
+PKG_VERSION_PATH=github.com/jfrog/terraform-provider-xray/${PKG_NAME}
 #VERSION := $(shell git tag --sort=-creatordate | head -1 | sed  -n 's/v\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1.\2.\3/p')
 # Replace explicit version after the first release
 VERSION := 0.0.0
 NEXT_VERSION := $(shell echo ${VERSION}| awk -F '.' '{print $$1 "." $$2 "." $$3 +1 }' )
+BINARY_NAME=terraform-provider-xray
+BUILD_PATH=terraform.d/plugins/registry.terraform.io/jfrog/xray/${NEXT_VERSION}/darwin_amd64
 
 default: build
 
 install:
-	mkdir -p terraform.d/plugins/registry.terraform.io/jfrog/xray/${NEXT_VERSION}/darwin_amd64 && \
-		(test -f terraform-provider-xray || go build -ldflags="-X 'xray.Version=${NEXT_VERSION}'") && \
-		mv terraform-provider-xray terraform.d/plugins/registry.terraform.io/jfrog/xray/${NEXT_VERSION}/darwin_amd64 && \
+	mkdir -p ${BUILD_PATH} && \
+		(test -f ${BINARY_NAME} || go build -ldflags="-X '${PKG_VERSION_PATH}.Version=${NEXT_VERSION}'") && \
+		mv ${BINARY_NAME} ${BUILD_PATH} && \
 		terraform init
 
 clean:
-	rm -fR .terraform.d/ .terraform terraform.tfstate* terraform.d/
+	rm -fR .terraform.d/ .terraform terraform.tfstate* terraform.d/ .terraform.lock.hcl
 
 release:
-	@git tag ${NEXT_VERSION} && git push --mirror
-	@echo "Pushed ${NEXT_VERSION}"
+	@git tag v${NEXT_VERSION} && git push --mirror
+	@echo "Pushed v${NEXT_VERSION}"
 
 build: fmtcheck
 	go build -ldflags="-X 'xray.Version=${NEXT_VERSION}'"
 
 debug_install:
-	mkdir -p terraform.d/plugins/registry.terraform.io/jfrog/xray/${NEXT_VERSION}/darwin_amd64 && \
-		(test -f terraform-provider-xray || go build -gcflags "all=-N -l" -ldflags="-X 'xray.Version=${NEXT_VERSION}-develop'") && \
-		mv terraform-provider-xray terraform.d/plugins/registry.terraform.io/jfrog/xray/${NEXT_VERSION}/darwin_amd64 && \
+	mkdir -p ${BUILD_PATH} && \
+		(test -f ${BINARY_NAME} || go build -gcflags "all=-N -l" -ldflags="-X '${PKG_VERSION_PATH}.Version=${NEXT_VERSION}-develop'") && \
+		mv ${BINARY_NAME} ${BUILD_PATH} && \
 		terraform init
 
 
@@ -38,18 +41,18 @@ attach:
 	dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient attach $$(pgrep terraform-provider-xray)
 
 acceptance: fmtcheck
-	export TF_ACC=1
-	test -n ARTIFACTORY_USERNAME && test -n ARTIFACTORY_URL && test -n ARTIFACTORY_ACCESS_TOKEN \
-		&& go test -v -parallel 20 ./pkg/...
-
+	export TF_ACC=1 && go test -v -parallel 20 ./pkg/...
 
 fmt:
 	@echo "==> Fixing source code with gofmt..."
 	@gofmt -s -w ./$(PKG_NAME)
-	(command -v goimports &> /dev/null || go get golang.org/x/tools/cmd/goimports) && goimports -w pkg/xray
+	(command -v goimports &> /dev/null || go get golang.org/x/tools/cmd/goimports) && goimports -w ${PKG_NAME}
 
 fmtcheck:
 	@echo "==> Checking that code complies with gofmt requirements..."
 	@sh -c "find . -name '*.go' -not -name '*vendor*' -print0 | xargs -0 gofmt -l -s"
 
+doc:
+	go generate
+
 .PHONY: build fmt
diff --git a/docs/debug.md b/docs/debug.md
index 1264b390..f9775184 100644
--- a/docs/debug.md
+++ b/docs/debug.md
@@ -1,4 +1,4 @@
-#  Debugging a TerraForm provider 
+#  Debugging a TerraForm provider
 
 ## Understanding the design
 
@@ -6,46 +6,46 @@ In order to do it, you first have to understand how Go builds apps, and then how
 
 Every terraform provider is a sort of `module`. In order to support an open, modular system, in almost any language, you need to be able to dynamically load modules and interact with them. Terraform is no exception.
 
-However, the go lang team long ago decided to compile to statically linked applications; 
-any dependencies you have will be compiled into 1 single binary. Unlike in other native languages (like C, or C++), a 
+However, the go lang team long ago decided to compile to statically linked applications;
+any dependencies you have will be compiled into 1 single binary. Unlike in other native languages (like C, or C++), a
 `.dll` or `.so` is not used; there is no dynamic library to load at runtime and thus, modularity becomes a whole other trick.
-This is done to avoid the notorious **dll hell** that was so common up until most modern systems included some 
+This is done to avoid the notorious **dll hell** that was so common up until most modern systems included some
 kind of dependency management. And yes, it can still be an issue.
 
-Every terraform provider is its own mini RPC server. When terraform runs your provider, it actually starts a new process that is your provider, and connects to it through 
-this RPC channel. Compounding the problem is that the lifetime of your provider process is very much 
+Every terraform provider is its own mini RPC server. When terraform runs your provider, it actually starts a new process that is your provider, and connects to it through
+this RPC channel. Compounding the problem is that the lifetime of your provider process is very much
 ephemeral; potentially lasting no more and a few seconds. It's this process you need to connect to with your debugger
 
 ### Normal debugging
 Normally, you would directly spin-up your app, and it would load modules into application memory. That's why you can actually
-debug it, because your debugger knows how to find the exact memory address for your provider. However, you don't have 
-this arrangement, and you need to do a _remote_ debug session. 
+debug it, because your debugger knows how to find the exact memory address for your provider. However, you don't have
+this arrangement, and you need to do a _remote_ debug session.
 
 ### The conundrum
-So, you don't load terraform directly, and even if you did, your `module` (a.k.a your provider) is in the memory 
-space of an entirely different process; and that lasts no more than a few seconds, potentially.  
+So, you don't load terraform directly, and even if you did, your `module` (a.k.a your provider) is in the memory
+space of an entirely different process; and that lasts no more than a few seconds, potentially.
 
 ## The solution
 
 1. You need the debugging tool [delve](https://github.com/go-delve/delve).
 2. You are going to have to place a little bit of shim code close to the spot in the code where you want to begin
-debugging. We need to stop this provider process from exiting before we can connect. So, put this bit of code in place:
+   debugging. We need to stop this provider process from exiting before we can connect. So, put this bit of code in place:
 ```go
 	connected := false
-	for !connected {
-		time.Sleep(time.Second) // set breakpoint here
-	}
+    for !connected {
+        time.Sleep(time.Second) // set breakpoint here
+    }
 ```
 This code effectively creates an infinite sleep loop; but that's actually essential to solving the problem.
 
-3. Place a break point right inside this loop. It won't do anything, yet. 
+3. Place a break point right inside this loop. It won't do anything, yet.
 4. Now run the terraform commands you need to, to engage the code you're desiring to debug. Upon doing so,
-terraform will basically stop, as it waits on a response from you provider; because you put an infinite sleep loop in
+   terraform will basically stop, as it waits on a response from you provider; because you put an infinite sleep loop in
 5. You must now tell `delve` to connect to this remote process using it's PID. This isn't as hard as it seems.
-Run this commands:
-`dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient attach $(pgrep terraform-provider-xray)`
-The last argument gets the `PID` for your provider and supplies it to `delve` to connect. Immediately upon running this 
-command, you're going to hit your break point. Please make sure to substitute `terraform-provider-xray` for your provider name
-6. To exit this infinite loop, use your debugger to set `connected` to `true`. By doing so you change the loop predicate 
-and it will exit this loop on the next iteration.
+   Run this commands:
+   `dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient attach $(pgrep terraform-provider-xray)`
+   The last argument gets the `PID` for your provider and supplies it to `delve` to connect. Immediately upon running this
+   command, you're going to hit your break point. Please make sure to substitute `terraform-provider-xray` for your provider name
+6. To exit this infinite loop, use your debugger to set `connected` to `true`. By doing so you change the loop predicate
+   and it will exit this loop on the next iteration.
 7. *DEBUG!* - At this point you can, step, watch, drop the call stack, etc. Your whole arsenel is available
diff --git a/docs/index.md b/docs/index.md
index 63299149..9a471f89 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,1 +1,181 @@
+---
+layout: ""
+page_title: "JFrog Xray Provider"
+description: |-
+  The Xray provider is used to interact with the resources supported by JFrog Xray.
+---
+
 # JFrog Xray Provider
+
+The [Xray](https://jfrog.com/xray/) provider is used to interact with the
+resources supported by JFrog Xray. Xray is a part of JFrog Artifactory and can't be used separately.
+The provider needs to be configured with the proper credentials before it can be used.
+Xray API documentation can be found [here](https://www.jfrog.com/confluence/display/JFROG/Xray+REST+API)
+
+Links to documentation for specific resources can be found in the table of contents to the left.
+
+This provider requires access to Artifactory and Xray APIs, which are only available in the _licensed_ pro and enterprise editions.
+You can determine which license you have by accessing the following URL
+`${host}/artifactory/api/system/licenses/`
+
+You can either access it via api, or web browser - it does require admin level credentials, but it's one of the few APIs that will work without a license (side node: you can also install your license here with a `POST`)
+
+```bash
+curl -sL ${host}/projects/api/system/licenses/ | jq .
+{
+  "type" : "Enterprise Plus Trial",
+  "validThrough" : "Jan 29, 2022",
+  "licensedTo" : "JFrog Ltd"
+}
+```
+
+The following 3 license types (`jq .type`) do **NOT** support APIs:
+- Community Edition for C/C++
+- JCR Edition
+- OSS
+
+## Example Usage
+
+```terraform
+# Required for Terraform 0.13 and up (https://www.terraform.io/upgrade-guides/0-13.html)
+terraform {
+  required_providers {
+    xray = {
+      source  = "registry.terraform.io/jfrog/xray"
+      version = "0.0.1"
+    }
+  }
+}
+
+provider "xray" {
+  url          = "artifactory.site.com/xray"
+  access_token = "abc..xy"
+  // Also user can supply the following env vars:
+  // ARTIFACTORY_URL or JFROG_URL
+  // XRAY_ACCESS_TOKEN or JFROG_ACCESS_TOKEN
+}
+
+resource "random_id" "randid" {
+  byte_length = 2
+}
+
+resource "xray_security_policy" "security_policy" {
+  name        = "test-security-policy-severity-${random_id.randid.dec}"
+  description = "Security policy description"
+  type        = "security"
+
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+
+    criteria {
+      min_severity = "High"
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      build_failure_grace_period_in_days = 5     // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
+
+
+resource "xray_license_policy" "license_policy" {
+  name        = "test-license-policy-allowed-${random_id.randid.dec}"
+  description = "License policy, allow certain licenses"
+  type        = "license"
+
+  rule {
+    name     = "License_rule"
+    priority = 1
+
+    criteria {
+      allowed_licenses         = ["Apache-1.0", "Apache-2.0"]
+      allow_unknown            = false
+      multi_license_permissive = true
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = false
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      custom_severity                    = "High"
+      build_failure_grace_period_in_days = 5 // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
+
+resource "xray_watch" "all-repos" {
+  name        = "all-repos-watch-${random_id.randid.dec}"
+  description = "Watch for all repositories, matching the filter"
+  active      = true
+
+  watch_resource {
+    type = "all-repos"
+
+    filter {
+      type  = "regex"
+      value = ".*"
+    }
+  }
+
+  assigned_policy {
+    name = xray_security_policy.security_policy.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.license_policy.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
+```
+
+## Authentication
+
+The Xray provider supports one type of authentication using Bearer token.
+
+### Bearer Token
+Artifactory access tokens may be used via the Authorization header by providing the `access_token` field to the provider
+block. Getting this value from the environment is supported with the `XRAY_ACCESS_TOKEN`,
+or `JFROG_ACCESS_TOKEN` variables.
+Set `url` field to provide JFrog Xray URL. Alternatively you can set `ARTIFACTORY_URL`, `JFROG_URL` or `PROJECTS_URL` variables.
+
+Usage:
+```hcl
+# Configure the Xray provider
+provider "xray" {
+  url = "artifactory.site.com/xray"
+  access_token = "abc...xy"
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- **access_token** (String, Sensitive) This is a bearer token that can be given to you by your admin under `Identity and Access`
+- **url** (String) URL of Artifactory. This can also be sourced from the `XRAY_URL` or `JFROG_URL` environment variable. Default to 'http://localhost:8081' if not set.
diff --git a/docs/resources/artifactory_access_token.md b/docs/resources/artifactory_access_token.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/resources/license_policy.md b/docs/resources/license_policy.md
new file mode 100644
index 00000000..348185d3
--- /dev/null
+++ b/docs/resources/license_policy.md
@@ -0,0 +1,157 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "xray_license_policy Resource - terraform-provider-xray"
+subcategory: ""
+description: |-
+  Creates an xray policy using V2 of the underlying APIs. Please note: It's only compatible with Bearer token auth method (Identity and Access => Access Tokens
+---
+
+# xray_license_policy (Resource)
+
+Creates an xray policy using V2 of the underlying APIs. Please note: It's only compatible with Bearer token auth method (Identity and Access => Access Tokens
+
+## Example Usage
+
+```terraform
+resource "xray_license_policy" "allowed_licenses" {
+  name        = "test-license-policy-allowed"
+  description = "License policy, allow certain licenses"
+  type        = "license"
+
+  rule {
+    name     = "License_rule"
+    priority = 1
+
+    criteria {
+      allowed_licenses         = ["Apache-1.0", "Apache-2.0"]
+      allow_unknown            = false
+      multi_license_permissive = true
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = false
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      custom_severity                    = "High"
+      build_failure_grace_period_in_days = 5 // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+
+    }
+  }
+}
+
+resource "xray_license_policy" "banned_licenses" {
+  name        = "test-license-policy-banned"
+  description = "License policy, block certain licenses"
+  type        = "license"
+
+  rule {
+    name     = "License_rule"
+    priority = 1
+
+    criteria {
+      banned_licenses          = ["Apache-3.0", "Apache-4.0"]
+      allow_unknown            = false
+      multi_license_permissive = false
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = false
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      custom_severity                    = "Medium"
+      build_failure_grace_period_in_days = 5 // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Required
+
+- **name** (String) Name of the policy (must be unique)
+- **rule** (Block List, Min: 1) Nested block describing a policy rule. Described below (see [below for nested schema](#nestedblock--rule))
+- **type** (String) Type of the policy
+
+### Optional
+
+- **description** (String) More verbose description of the policy
+- **id** (String) The ID of this resource.
+
+### Read-Only
+
+- **author** (String) User, who created the policy
+- **created** (String) Creation timestamp
+- **modified** (String) Modification timestamp
+
+<a id="nestedblock--rule"></a>
+### Nested Schema for `rule`
+
+Required:
+
+- **criteria** (Block Set, Min: 1) Nested block describing the criteria for the policy. Described below (see [below for nested schema](#nestedblock--rule--criteria))
+- **name** (String) Name of the rule
+- **priority** (Number) Integer describing the rule priority. Must be at least 1
+
+Optional:
+
+- **actions** (Block Set, Max: 1) Nested block describing the actions to be applied by the policy. Described below. (see [below for nested schema](#nestedblock--rule--actions))
+
+<a id="nestedblock--rule--criteria"></a>
+### Nested Schema for `rule.criteria`
+
+Optional:
+
+- **allow_unknown** (Boolean) A violation will be generated for artifacts with unknown licenses (`true` or `false`).
+- **allowed_licenses** (Set of String) A list of OSS license names that may be attached to a component.
+- **banned_licenses** (Set of String) A list of OSS license names that may not be attached to a component.
+- **multi_license_permissive** (Boolean) Do not generate a violation if at least one license is valid in cases whereby multiple licenses were detected on the component
+
+
+<a id="nestedblock--rule--actions"></a>
+### Nested Schema for `rule.actions`
+
+Required:
+
+- **block_download** (Block Set, Min: 1, Max: 1) Nested block describing artifacts that should be blocked for download if a violation is triggered. Described below. (see [below for nested schema](#nestedblock--rule--actions--block_download))
+
+Optional:
+
+- **block_release_bundle_distribution** (Boolean) Blocks Release Bundle distribution to Edge nodes if a violation is found.
+- **build_failure_grace_period_in_days** (Number) Allow grace period for certain number of days. All violations will be ignored during this time. To be used only if `fail_build` is enabled.
+- **create_ticket_enabled** (Boolean) Create Jira Ticket for this Policy Violation. Requires configured Jira integration.
+- **custom_severity** (String) The severity of violation to be triggered if the `criteria` are met.
+- **fail_build** (Boolean) Whether or not the related CI build should be marked as failed if a violation is triggered. This option is only available when the policy is applied to an `xray_watch` resource with a `type` of `builds`.
+- **mails** (Set of String) A list of email addressed that will get emailed when a violation is triggered.
+- **notify_deployer** (Boolean) Sends an email message to component deployer with details about the generated Violations.
+- **notify_watch_recipients** (Boolean) Sends an email message to all configured recipients inside a specific watch with details about the generated Violations.
+- **webhooks** (Set of String) A list of Xray-configured webhook URLs to be invoked if a violation is triggered.
+
+<a id="nestedblock--rule--actions--block_download"></a>
+### Nested Schema for `rule.actions.block_download`
+
+Required:
+
+- **active** (Boolean) Whether or not to block download of artifacts that meet the artifact and severity `filters` for the associated `xray_watch` resource.
+- **unscanned** (Boolean) Whether or not to block download of artifacts that meet the artifact `filters` for the associated `xray_watch` resource but have not been scanned yet.
+
+
diff --git a/docs/resources/security_policy.md b/docs/resources/security_policy.md
new file mode 100644
index 00000000..135e6450
--- /dev/null
+++ b/docs/resources/security_policy.md
@@ -0,0 +1,160 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "xray_security_policy Resource - terraform-provider-xray"
+subcategory: ""
+description: |-
+  Creates an xray policy using V2 of the underlying APIs. Please note: It's only compatible with Bearer token auth method (Identity and Access => Access Tokens
+---
+
+# xray_security_policy (Resource)
+
+Creates an xray policy using V2 of the underlying APIs. Please note: It's only compatible with Bearer token auth method (Identity and Access => Access Tokens
+
+## Example Usage
+
+```terraform
+resource "xray_security_policy" "min_severity" {
+  name        = "test-security-policy-severity"
+  description = "Security policy description"
+  type        = "security"
+
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+
+    criteria {
+      min_severity = "High"
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      build_failure_grace_period_in_days = 5     // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
+
+resource "xray_security_policy" "cvss_score" {
+  name        = "test-security-policy-cvss"
+  description = "Security policy description"
+  type        = "security"
+
+  rule {
+    name     = "rule-name-cvss"
+    priority = 1
+
+    criteria {
+
+      cvss_range {
+        from = 1.5
+        to   = 5.3
+      }
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      build_failure_grace_period_in_days = 5     // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Required
+
+- **name** (String) Name of the policy (must be unique)
+- **rule** (Block List, Min: 1) Nested block describing security rule. Described below (see [below for nested schema](#nestedblock--rule))
+- **type** (String) Type of the policy
+
+### Optional
+
+- **description** (String) More verbose description of the policy
+- **id** (String) The ID of this resource.
+
+### Read-Only
+
+- **author** (String) User, who created the policy
+- **created** (String) Creation timestamp
+- **modified** (String) Modification timestamp
+
+<a id="nestedblock--rule"></a>
+### Nested Schema for `rule`
+
+Required:
+
+- **criteria** (Block Set, Min: 1, Max: 1) Nested block describing the criteria for the policy. Described below. (see [below for nested schema](#nestedblock--rule--criteria))
+- **name** (String) Name of the rule
+- **priority** (Number) Integer describing the rule priority. Must be at least 1
+
+Optional:
+
+- **actions** (Block Set, Max: 1) Nested block describing the actions to be applied by the policy. Described below. (see [below for nested schema](#nestedblock--rule--actions))
+
+<a id="nestedblock--rule--criteria"></a>
+### Nested Schema for `rule.criteria`
+
+Optional:
+
+- **cvss_range** (Block List, Max: 1) Nested block describing a CVS score range to be impacted. Defined below. (see [below for nested schema](#nestedblock--rule--criteria--cvss_range))
+- **min_severity** (String) The minimum security vulnerability severity that will be impacted by the policy.
+
+<a id="nestedblock--rule--criteria--cvss_range"></a>
+### Nested Schema for `rule.criteria.cvss_range`
+
+Required:
+
+- **from** (Number) The beginning of the range of CVS scores (from 1-10, float) to flag.
+- **to** (Number) The end of the range of CVS scores (from 1-10, float) to flag.
+
+
+
+<a id="nestedblock--rule--actions"></a>
+### Nested Schema for `rule.actions`
+
+Required:
+
+- **block_download** (Block Set, Min: 1, Max: 1) Nested block describing artifacts that should be blocked for download if a violation is triggered. Described below. (see [below for nested schema](#nestedblock--rule--actions--block_download))
+
+Optional:
+
+- **block_release_bundle_distribution** (Boolean) Blocks Release Bundle distribution to Edge nodes if a violation is found.
+- **build_failure_grace_period_in_days** (Number) Allow grace period for certain number of days. All violations will be ignored during this time. To be used only if `fail_build` is enabled.
+- **create_ticket_enabled** (Boolean) Create Jira Ticket for this Policy Violation. Requires configured Jira integration.
+- **fail_build** (Boolean) Whether or not the related CI build should be marked as failed if a violation is triggered. This option is only available when the policy is applied to an `xray_watch` resource with a `type` of `builds`.
+- **mails** (Set of String) A list of email addressed that will get emailed when a violation is triggered.
+- **notify_deployer** (Boolean) Sends an email message to component deployer with details about the generated Violations.
+- **notify_watch_recipients** (Boolean) Sends an email message to all configured recipients inside a specific watch with details about the generated Violations.
+- **webhooks** (Set of String) A list of Xray-configured webhook URLs to be invoked if a violation is triggered.
+
+<a id="nestedblock--rule--actions--block_download"></a>
+### Nested Schema for `rule.actions.block_download`
+
+Required:
+
+- **active** (Boolean) Whether or not to block download of artifacts that meet the artifact and severity `filters` for the associated `xray_watch` resource.
+- **unscanned** (Boolean) Whether or not to block download of artifacts that meet the artifact `filters` for the associated `xray_watch` resource but have not been scanned yet.
+
+
diff --git a/docs/resources/watch.md b/docs/resources/watch.md
new file mode 100644
index 00000000..0fad9f93
--- /dev/null
+++ b/docs/resources/watch.md
@@ -0,0 +1,160 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "xray_watch Resource - terraform-provider-xray"
+subcategory: ""
+description: |-
+  Provides an Xray watch resource.
+---
+
+# xray_watch (Resource)
+
+Provides an Xray watch resource.
+
+## Example Usage
+
+```terraform
+resource "xray_watch" "all-repos" {
+  name        = "all-repos-watch"
+  description = "Watch for all repositories, matching the filter"
+  active      = true
+
+  watch_resource {
+    type = "all-repos"
+
+    filter {
+      type  = "regex"
+      value = ".*"
+    }
+  }
+
+  assigned_policy {
+    name = xray_security_policy.allowed_licenses.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.banned_licenses.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
+
+resource "xray_watch" "repository" {
+  name        = "repository-watch"
+  description = "Watch a single repo or a list of repositories"
+  active      = true
+
+  watch_resource {
+    type       = "repository"
+    bin_mgr_id = "default"
+    name       = "your-repository-name"
+
+    filter {
+      type  = "regex"
+      value = ".*"
+    }
+  }
+
+  watch_resource {
+    type       = "repository"
+    bin_mgr_id = "default"
+    name       = "your-other-repository-name"
+
+    filter {
+      type  = "package-type"
+      value = "Docker"
+    }
+  }
+
+  assigned_policy {
+    name = xray_security_policy.min_severity.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.cvss_range.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
+
+resource "xray_watch" "build" {
+  name        = "build-watch"
+  description = "Watch a single build or a list of builds"
+  active      = true
+
+  watch_resource {
+    type       = "build"
+    bin_mgr_id = "default"
+    name       = "your-build-name"
+  }
+
+  watch_resource {
+    type       = "build"
+    bin_mgr_id = "default"
+    name       = "your-other-build-name"
+  }
+
+  assigned_policy {
+    name = xray_security_policy.min_severity.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.cvss_range.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Required
+
+- **assigned_policy** (Block Set, Min: 1) Nested argument describing policies that will be applied. Defined below. (see [below for nested schema](#nestedblock--assigned_policy))
+- **name** (String) Name of the watch (must be unique)
+- **watch_resource** (Block Set, Min: 1) Nested argument describing the resources to be watched. Defined below. (see [below for nested schema](#nestedblock--watch_resource))
+
+### Optional
+
+- **active** (Boolean) Whether or not the watch is active
+- **description** (String) Description of the watch
+- **id** (String) The ID of this resource.
+- **watch_recipients** (Set of String) A list of email addressed that will get emailed when a violation is triggered.
+
+<a id="nestedblock--assigned_policy"></a>
+### Nested Schema for `assigned_policy`
+
+Required:
+
+- **name** (String) The name of the policy that will be applied
+- **type** (String) The type of the policy - security or license
+
+
+<a id="nestedblock--watch_resource"></a>
+### Nested Schema for `watch_resource`
+
+Required:
+
+- **type** (String) Type of resource to be watched. Options: `all-repos`, `repository`, `build`, `project`, `all-projects`.
+
+Optional:
+
+- **bin_mgr_id** (String) The ID number of a binary manager resource. Should be set to `default` if not set on the Artifactory side.
+- **filter** (Block List) Nested argument describing filters to be applied. Defined below. (see [below for nested schema](#nestedblock--watch_resource--filter))
+- **name** (String) The name of the build or repository. Enable Xray indexing must be enabled on the repo or build
+
+<a id="nestedblock--watch_resource--filter"></a>
+### Nested Schema for `watch_resource.filter`
+
+Required:
+
+- **type** (String) The type of filter, such as `regex`, `package-type` or `ant-patterns`
+- **value** (String) The value of the filter, such as the text of the regex or name of the package type.
+
+
diff --git a/docs/resources/xray_policy.md b/docs/resources/xray_policy.md
deleted file mode 100644
index f82575d8..00000000
--- a/docs/resources/xray_policy.md
+++ /dev/null
@@ -1,118 +0,0 @@
-# Xray Policy Resource
-
-Provides an Xray policy resource. This can be used to create and manage Xray v1 policies.
-
-## Example Usage
-
-```hcl
-# Create a new Xray license policy
-resource "xray_policy" "example" {
-  name  = "policy-name"
-  description = "license policy description"
-  type = "license"
-
-  rules {
-    name = "license rule"
-    priority = 1
-    criteria {
-      allowed_licenses = ["0BSD", "AAL"]
-    }
-  }
-}
-
-# Create a new Xray watch for all repositories and assign the policy
-resource "xray_watch" "example" {
-  name  = "watch-name"
-  description = "watching all repositories"
-  resources {
-    type = "all-repos"
-    name = "All Repositories"
-  }
-  assigned_policies {
-    name = xray_policy.example.name
-    type = "license"
-  }
-}
-```
-
-## Attribute Reference
-
-The following arguments are supported:
-
-* `name` - (Required) Name of the policy (must be unique)
-* `type` - (Required) Type of the policy
-* `description` - (Optional) More verbose description of the policy
-* `author` - (Optional) Name of the policy author
-* `rules` - (Required) Nested block describing the policy rules. Described below.
-
-### Rules
-
-The top-level `rules` block is a list of one or more rules that each supports the following:
-
-* `name` - (Required) Name of the rule
-* `priority` - (Required) Integer describing the rule priority
-* `criteria` - (Required) Nested block describing the criteria for the policy. Described below.
-* `actions` - (Required) Nested block describing the actions to be applied by the policy. Described below.
-
-#### criteria
-
-~> **NOTE:** Only one of either security criteria (`min_severity` and `cvss_range`) or license criteria (`allow_unknown`,
-`banned_licenses`, and `allowed_licenses`) may be specified. While all attributes are marked as optional, at least one
-attribute from only one of these groups must be defined.
-
-The nested `criteria` block is a list of one item, supporting the following:
-
-##### Security criteria
-
-* `min_severity` - (Optional) The minimum security vulnerability severity that will be impacted by the policy.
-* `cvss_range` - (Optional) Nested block describing a CVS score range to be impacted. Defined below.
-
-###### cvss_range
-
-The nested `cvss_range` block is a list of one object that contains the following attributes:
-
-* `to` - (Required) The end of the range of CVS scores (from 1-10) to flag. 
-* `from` - (Required) The beginning of the range of CVS scores (from 1-10) to flag.
-
-##### License criteria
-
-* `allow_unknown` - (Optional) Whether or not to allow components whose license cannot be determined (`true` or `false`).
-* `banned_licenses` - (Optional) A list of OSS license names that may not be attached to a component.
-* `allowed_licenses` - (Optional) A list of OSS license names that may be attached to a component.
-
-#### actions
-
-~> **NOTE:** While all of the actions attributes are marked as optional, at least one action must be specified.
-
-The nested `actions` block is a list of exactly one object with the following attributes:
-
-* `mails` - (Optional) A list of email addressed that will get emailed when a violation is triggered.
-* `fail_build` - (Optional) Whether or not the related CI build should be marked as failed if a violation is triggered. This option is only available when the policy is applied to an `xray_watch` resource with a `type` of `builds`.
-* `block_download` - (Optional) Nested block describing artifacts that should be blocked for download if a violation is triggered. Described below.
-* `webhooks` - (Optional) A list of Xray-configured webhook URLs to be invoked if a violation is triggered.
-* `custom_severity` - (Optional) The severity of violation to be triggered if the `criteria` are met.
-
-###### block_download
-
-~> **NOTE:** Only one of `unscanned` or `active` may be set to `true`.
-
-The nested `block_download` block is a list of exactly one object with the following attributes:
-
-* `unscanned` - Whether or not to block download of artifacts that meet the artifact `filters` for the associated `xray_watch` resource but have not been scanned yet.
-* `active` - Whether or not to block download of artifacts that meet the artifact and severity `filters` for the associated `xray_watch` resource.
-
-
-## Attributes Reference
-
-In addition to all arguments above, the following attributes are exported:
-
-* `created` - Timestamp of when the policy was first created
-* `modified` - Timestamp of when the policy was last modified
-
-## Import
-
-A policy can be imported by using the name, e.g.
-
-```
-$ terraform import xray_policy.example policy-name
-```
diff --git a/docs/resources/xray_watch.md b/docs/resources/xray_watch.md
deleted file mode 100644
index 1e021e24..00000000
--- a/docs/resources/xray_watch.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# Xray Watch Resource
-
-Provides a Xray watch resource.
-
-## Example Usage
-
-```hcl
-# Create a new Xray watch for all repositories
-resource "xray_watch" "example" {
-  name  = "watch-name"
-  description = "watching all repositories"
-  resources {
-    type = "all-repos"
-    name = "All Repositories"
-  }
-  assigned_policies {
-    name = xray_policy.example.name
-    type = "license"
-  }
-}
-```
-
-## Argument Reference
-
-The following arguments are supported:
-
-* `name` - (Required) Name of the watch (must be unique)
-* `description` - (Optional) Description of the watch
-* `active` - (Optional) Whether or not the watch will be active
-* `resources` - (Required) Nested argument describing the resources to be watched. Defined below.
-* `assigned_policies` - (Required) Nested argument describing policies that will be applied. Defined below.
-
-### resources
-
-The top-level `resources` block contains a list of one or more resource objects that each support the following:
-
-* `type` - (Required) Type of resource to be watched
-* `name` - (Required) A name describing the resource
-* `bin_mgr_id` - (Optional) The ID number of a binary manager resource
-* `repo_type` - (Optional) Type of repository (e.g. local or remote)
-* `filters` - (Optional) Nested argument describing filters to be applied. Defined below.
-
-#### filters
-
-The nested `filters` block contains a list of one or more filters to be applied, each of which supports the following:
-
-* `type` - (Required) The type of filter, such as `regex` or `package-type`
-* `value` - (Required) The value of the filter, such as the text of the regex or name of the package type
-
-### assigned_policies
-
-The top-level `assigned_policies` block contains a list of one or more policy objects that each support the following:
-
-* `name` - (Required) The name of the policy that will be applied
-* `type` - (Required) The type of the policy
-
-
-## Import
-
-Watches can be imported using their name, e.g.
-
-```
-$ terraform import xray_watch.example watch-name
-```
diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf
new file mode 100644
index 00000000..8261a1de
--- /dev/null
+++ b/examples/provider/provider.tf
@@ -0,0 +1,4 @@
+provider "xray" {
+  url          = "${var.artifactory_url}/xray"
+  access_token = var.xray_access_token
+}
diff --git a/examples/resources/xray_license_policy/resource.tf b/examples/resources/xray_license_policy/resource.tf
new file mode 100644
index 00000000..a233d1ab
--- /dev/null
+++ b/examples/resources/xray_license_policy/resource.tf
@@ -0,0 +1,68 @@
+resource "xray_license_policy" "allowed_licenses" {
+  name        = "test-license-policy-allowed"
+  description = "License policy, allow certain licenses"
+  type        = "license"
+
+  rule {
+    name     = "License_rule"
+    priority = 1
+
+    criteria {
+      allowed_licenses         = ["Apache-1.0", "Apache-2.0"]
+      allow_unknown            = false
+      multi_license_permissive = true
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = false
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      custom_severity                    = "High"
+      build_failure_grace_period_in_days = 5 // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+
+    }
+  }
+}
+
+resource "xray_license_policy" "banned_licenses" {
+  name        = "test-license-policy-banned"
+  description = "License policy, block certain licenses"
+  type        = "license"
+
+  rule {
+    name     = "License_rule"
+    priority = 1
+
+    criteria {
+      banned_licenses          = ["Apache-3.0", "Apache-4.0"]
+      allow_unknown            = false
+      multi_license_permissive = false
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = false
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      custom_severity                    = "Medium"
+      build_failure_grace_period_in_days = 5 // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/examples/resources/xray_security_policy/resource.tf b/examples/resources/xray_security_policy/resource.tf
new file mode 100644
index 00000000..6ef8e95f
--- /dev/null
+++ b/examples/resources/xray_security_policy/resource.tf
@@ -0,0 +1,65 @@
+resource "xray_security_policy" "min_severity" {
+  name        = "test-security-policy-severity"
+  description = "Security policy description"
+  type        = "security"
+
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+
+    criteria {
+      min_severity = "High"
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      build_failure_grace_period_in_days = 5     // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
+
+resource "xray_security_policy" "cvss_score" {
+  name        = "test-security-policy-cvss"
+  description = "Security policy description"
+  type        = "security"
+
+  rule {
+    name     = "rule-name-cvss"
+    priority = 1
+
+    criteria {
+
+      cvss_range {
+        from = 1.5
+        to   = 5.3
+      }
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      build_failure_grace_period_in_days = 5     // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/examples/resources/xray_watch/resource.tf b/examples/resources/xray_watch/resource.tf
new file mode 100644
index 00000000..79bf5bcc
--- /dev/null
+++ b/examples/resources/xray_watch/resource.tf
@@ -0,0 +1,96 @@
+resource "xray_watch" "all-repos" {
+  name        = "all-repos-watch"
+  description = "Watch for all repositories, matching the filter"
+  active      = true
+
+  watch_resource {
+    type = "all-repos"
+
+    filter {
+      type  = "regex"
+      value = ".*"
+    }
+  }
+
+  assigned_policy {
+    name = xray_security_policy.allowed_licenses.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.banned_licenses.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
+
+resource "xray_watch" "repository" {
+  name        = "repository-watch"
+  description = "Watch a single repo or a list of repositories"
+  active      = true
+
+  watch_resource {
+    type       = "repository"
+    bin_mgr_id = "default"
+    name       = "your-repository-name"
+
+    filter {
+      type  = "regex"
+      value = ".*"
+    }
+  }
+
+  watch_resource {
+    type       = "repository"
+    bin_mgr_id = "default"
+    name       = "your-other-repository-name"
+
+    filter {
+      type  = "package-type"
+      value = "Docker"
+    }
+  }
+
+  assigned_policy {
+    name = xray_security_policy.min_severity.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.cvss_range.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
+
+resource "xray_watch" "build" {
+  name        = "build-watch"
+  description = "Watch a single build or a list of builds"
+  active      = true
+
+  watch_resource {
+    type       = "build"
+    bin_mgr_id = "default"
+    name       = "your-build-name"
+  }
+
+  watch_resource {
+    type       = "build"
+    bin_mgr_id = "default"
+    name       = "your-other-build-name"
+  }
+
+  assigned_policy {
+    name = xray_security_policy.min_severity.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.cvss_range.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
\ No newline at end of file
diff --git a/examples/sample.tf b/examples/sample.tf
new file mode 100644
index 00000000..43096b91
--- /dev/null
+++ b/examples/sample.tf
@@ -0,0 +1,114 @@
+# Required for Terraform 0.13 and up (https://www.terraform.io/upgrade-guides/0-13.html)
+terraform {
+  required_providers {
+    xray = {
+      source  = "registry.terraform.io/jfrog/xray"
+      version = "0.0.1"
+    }
+  }
+}
+
+provider "xray" {
+  url          = "artifactory.site.com/xray"
+  access_token = "abc..xy"
+  // Also user can supply the following env vars:
+  // ARTIFACTORY_URL or JFROG_URL
+  // XRAY_ACCESS_TOKEN or JFROG_ACCESS_TOKEN
+}
+
+resource "random_id" "randid" {
+  byte_length = 2
+}
+
+resource "xray_security_policy" "security_policy" {
+  name        = "test-security-policy-severity-${random_id.randid.dec}"
+  description = "Security policy description"
+  type        = "security"
+
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+
+    criteria {
+      min_severity = "High"
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      build_failure_grace_period_in_days = 5     // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
+
+
+resource "xray_license_policy" "license_policy" {
+  name        = "test-license-policy-allowed-${random_id.randid.dec}"
+  description = "License policy, allow certain licenses"
+  type        = "license"
+
+  rule {
+    name     = "License_rule"
+    priority = 1
+
+    criteria {
+      allowed_licenses         = ["Apache-1.0", "Apache-2.0"]
+      allow_unknown            = false
+      multi_license_permissive = true
+    }
+
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_release_bundle_distribution  = false
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      custom_severity                    = "High"
+      build_failure_grace_period_in_days = 5 // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
+    }
+  }
+}
+
+resource "xray_watch" "all-repos" {
+  name        = "all-repos-watch-${random_id.randid.dec}"
+  description = "Watch for all repositories, matching the filter"
+  active      = true
+
+  watch_resource {
+    type = "all-repos"
+
+    filter {
+      type  = "regex"
+      value = ".*"
+    }
+  }
+
+  assigned_policy {
+    name = xray_security_policy.security_policy.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.license_policy.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
diff --git a/go.mod b/go.mod
index c82abd47..ea46c728 100644
--- a/go.mod
+++ b/go.mod
@@ -4,8 +4,9 @@ require (
 	github.com/go-resty/resty/v2 v2.6.1-0.20210916045937-1792d629c3c6
 	github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75
 	github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
+	github.com/hashicorp/terraform-plugin-docs v0.5.1 // indirect
 	github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0
-	golang.org/x/tools v0.1.5 // indirect
+	golang.org/x/tools v0.1.8 // indirect
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
 )
 
diff --git a/go.sum b/go.sum
index 77130b10..56da59b9 100644
--- a/go.sum
+++ b/go.sum
@@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
 cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
 cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0=
 cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
 cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
 cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
@@ -19,12 +18,15 @@ cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNF
 cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
 cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
 cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0 h1:PQcPefKFdaIzjQFbiyOgAqyx8q5djaE7x9Sqe712DPA=
 cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=
 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
 cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
 cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
 cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=
 cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
 cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
 cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
@@ -32,8 +34,11 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
 cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
 cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA=
 cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9 h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
 github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
@@ -48,12 +53,10 @@ github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C6
 github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
 github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
 github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
-github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
 github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
 github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=
 github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
-github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
-github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/andybalholm/crlf v0.0.0-20171020200849-670099aa064f h1:NNJE6p4LchkmNfNskDUaSbrwxZzr7t2/lj2aS+q4oF0=
 github.com/andybalholm/crlf v0.0.0-20171020200849-670099aa064f/go.mod h1:k8feO4+kXDxro6ErPXBRTJ/ro2mf0SsFG8s7doP9kJE=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
@@ -68,6 +71,7 @@ github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbj
 github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
 github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
 github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
@@ -78,26 +82,32 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1U
 github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
 github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/buger/jsonparser v0.0.0-20180910192245-6acdf747ae99/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cheggaaa/pb v1.0.27 h1:wIkZHkNfC7R6GI5w7l/PdAdzXzlrbcI3p8OAlnkTsnc=
 github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
+github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
-github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
-github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
 github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
 github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E=
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
@@ -114,8 +124,10 @@ github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2Su
 github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
 github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
 github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-resty/resty/v2 v2.6.1-0.20210916045937-1792d629c3c6 h1:oWZNNnHfHAE4z8uYHkuEqzueDjSgMNB+e80RCbrEyv8=
 github.com/go-resty/resty/v2 v2.6.1-0.20210916045937-1792d629c3c6/go.mod h1:fUytuqHwz8P28muStrLRS1B/V95zeSbTTR/lCHDSx3g=
@@ -128,18 +140,15 @@ github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4er
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
 github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
 github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
 github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
 github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
 github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
 github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
@@ -154,26 +163,18 @@ github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
-github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
-github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
-github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
-github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
 github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/martian/v3 v3.0.0 h1:pMen7vLs8nvgEYhywH3KDWJIJTeEr2ULsVWHWYHQyBs=
@@ -184,22 +185,21 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf
 github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
 github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
 github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99 h1:Ak8CrdlwwXwAZxzS66vgPt4U8yUZX7JwLvVR58FN5jM=
 github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk=
-github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
 github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY=
 github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
 github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
 github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
-github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
 github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
@@ -221,7 +221,6 @@ github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoD
 github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
 github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
 github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
 github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
 github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=
 github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
@@ -234,29 +233,32 @@ github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI
 github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
 github.com/hashicorp/terraform-exec v0.14.0 h1:UQoUcxKTZZXhyyK68Cwn4mApT4mnFPmEXPiqaHL9r+w=
 github.com/hashicorp/terraform-exec v0.14.0/go.mod h1:qrAASDq28KZiMPDnQ02sFS9udcqEkRly002EA2izXTA=
+github.com/hashicorp/terraform-exec v0.15.0 h1:cqjh4d8HYNQrDoEmlSGelHmg2DYDh5yayckvJ5bV18E=
+github.com/hashicorp/terraform-exec v0.15.0/go.mod h1:H4IG8ZxanU+NW0ZpDRNsvh9f0ul7C0nHP+rUR/CHs7I=
 github.com/hashicorp/terraform-json v0.12.0 h1:8czPgEEWWPROStjkWPUnTQDXmpmZPlkQAwYYLETaTvw=
 github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI=
+github.com/hashicorp/terraform-json v0.13.0 h1:Li9L+lKD1FO5RVFRM1mMMIBDoUHslOniyEi5CM+FWGY=
+github.com/hashicorp/terraform-json v0.13.0/go.mod h1:y5OdLBCT+rxbwnpxZs9kGL7R9ExU76+cpdY8zHwoazk=
+github.com/hashicorp/terraform-plugin-docs v0.5.1 h1:WwrUcamix9x0TqfTw/WGHMRqoTe1QPZKaeWJPuFb4lQ=
+github.com/hashicorp/terraform-plugin-docs v0.5.1/go.mod h1:SQwEgy0/B0UPQ07rNEG1Wpt6E3jvRcCwkVHPNybGgc0=
 github.com/hashicorp/terraform-plugin-go v0.3.0 h1:AJqYzP52JFYl9NABRI7smXI1pNjgR5Q/y2WyVJ/BOZA=
 github.com/hashicorp/terraform-plugin-go v0.3.0/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM=
 github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 h1:SuI59MqNjYDrL7EfqHX9V6P/24isgqYx/FdglwVs9bg=
 github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0/go.mod h1:grseeRo9g3yNkYW09iFlV8LG78jTa1ssBgouogQg/RU=
-github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
 github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
 github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
 github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
 github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
 github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
 github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
-github.com/jfrog/gofrog v1.0.6 h1:yUDxSCw8gTK6vC4PvtG0HTnEOQJSZ+O4lWGCgkev1nU=
-github.com/jfrog/gofrog v1.0.6/go.mod h1:HkDzg+tMNw23UryoOv0+LB94BzYcl6MCIoz8Tmlb+s8=
-github.com/jfrog/jfrog-client-go v0.27.0 h1:NHsxNOnighck3uPSTsNufBDa4/3sB3Rr1kwONNTezPo=
-github.com/jfrog/jfrog-client-go v0.27.0/go.mod h1:dR0Z+zjSAoMWT5phrPIVjj+kjYYHHAEq1JnvA7klwvI=
 github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
 github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
 github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -267,26 +269,20 @@ github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfE
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
 github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.11.2 h1:MiK62aErc3gIiVEtyzKfeOHgW7atJb5g/KNX5m3c2nQ=
 github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU=
-github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
-github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
-github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
 github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
 github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
@@ -295,82 +291,79 @@ github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlW
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
 github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
+github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
 github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
 github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
+github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
 github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
-github.com/mholt/archiver/v3 v3.5.1-0.20210618180617-81fac4ba96e4 h1:S7ICJmgiEB5WbKXg3CPL/qmJKxxKf33yJSkxqbdiTQA=
-github.com/mholt/archiver/v3 v3.5.1-0.20210618180617-81fac4ba96e4/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
 github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=
 github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
-github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
 github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
 github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
 github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
-github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
 github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 github.com/mitchellh/go-testing-interface v1.0.4 h1:ZU1VNC02qyufSZsjjs7+khruk2fKvbQ3TwRV/IBCeFA=
 github.com/mitchellh/go-testing-interface v1.0.4/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
 github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
 github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
 github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
 github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
 github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
 github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
 github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758=
 github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
-github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
-github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
 github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
 github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
 github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
-github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
-github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
-github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
-github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
+github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
+github.com/sebdah/goldie v1.0.0 h1:9GNhIat69MSlz/ndaBg48vl9dF5fI+NBB6kfOxgfkMc=
 github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
-github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
 github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc=
 github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
 github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
-github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
-github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
 github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
 github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
 github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
@@ -380,31 +373,29 @@ github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37w
 github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
 github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
 github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
-github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
-github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
-github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
-github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.1 h1:/vn0k+RBvwlxEmP5E7SZMqNxPhfMVFEJiykr15/0XKM=
+github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
-github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8=
 github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
 github.com/zclconf/go-cty v1.8.4 h1:pwhhz5P+Fjxse7S7UriBrMu6AUJSZM5pKqGem1PjGAs=
 github.com/zclconf/go-cty v1.8.4/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
+github.com/zclconf/go-cty v1.9.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
+github.com/zclconf/go-cty v1.10.0 h1:mp9ZXQeIcN8kAwuqorjH+Q+njbJKjLrvB2yIh4q7U+0=
+github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
+github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
 github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
 go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo=
 golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -414,8 +405,6 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -425,8 +414,10 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0
 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=
 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -440,6 +431,7 @@ golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPI
 golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
 golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
 golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=
 golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
 golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
 golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
@@ -449,6 +441,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
+golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
 golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -478,27 +472,26 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8=
 golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
+golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -507,7 +500,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dzugGxJ/SQHoNufZJq1w=
 golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -533,30 +525,30 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
 golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -569,7 +561,6 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0 h1:Dh6fw+p6FyRl5x/FvNswO1ji0lIGzm3KP8Y9VkS9PTE=
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -599,16 +590,16 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
 golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
 golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
+golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
 google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.9.0 h1:jbyannxz0XFD3zdjgrSUsaJbgpH4eTrkdhRChkHPfO8=
 google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
 google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
 google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
@@ -623,10 +614,8 @@ google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
 google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk=
 google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
@@ -638,7 +627,6 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn
 google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
 google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
@@ -665,7 +653,6 @@ google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEd
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
@@ -688,13 +675,14 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
 google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo=
 gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
+gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
@@ -702,9 +690,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@@ -714,7 +699,11 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=
 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
 rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/main.go b/main.go
index b3acb4f3..d6c74f72 100644
--- a/main.go
+++ b/main.go
@@ -5,6 +5,10 @@ import (
 	"github.com/jfrog/terraform-provider-xray/pkg/xray"
 )
 
+// Run the docs generation tool, check its repository for more information on how it works and how docs
+// can be customized.
+//go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
+
 func main() {
 	plugin.Serve(&plugin.ServeOpts{
 		ProviderFunc: xray.Provider,
diff --git a/pkg/xray/policies.go b/pkg/xray/policies.go
index 624652bf..b2d05bfb 100644
--- a/pkg/xray/policies.go
+++ b/pkg/xray/policies.go
@@ -2,392 +2,342 @@ package xray
 
 import (
 	"context"
+	"log"
+	"net/http"
+
 	"github.com/go-resty/resty/v2"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
-	"log"
-	"net/http"
 )
 
-// PolicyCVSSRange All of this was ripped out of it's original location and copied here.
-// The original provider code used th v1 API, which is not supported in the JFROG go client
-// The current objective is to rip out any dependencies not from jfrog. So, jfrog doesn't support it
-// I need backward compatibility, and I can't have any other dependencies.
-
 type PolicyCVSSRange struct {
-	To   float64 `json:"to,omitempty"`
-	From float64 `json:"from,omitempty"`
+	To   *float64 `json:"to,omitempty"`
+	From *float64 `json:"from,omitempty"`
 }
 
 type PolicyRuleCriteria struct {
 	// Security Criteria
-	MinimumSeverity string           `json:"min_severity,omitempty"`
+	MinimumSeverity string           `json:"min_severity,omitempty"` // Omitempty is used because the empty field is conflicting with CVSSRange
 	CVSSRange       *PolicyCVSSRange `json:"cvss_range,omitempty"`
+	// We use pointer for CVSSRange to address nil-verification for non-primitive types.
+	// Unlike primitive types, when the non-primitive type in the struct is set
+	// to nil, the empty key will be created in the JSON body anyway.
+	// Since CVSSRange is conflicting with MinimumSeverity, Xray will throw an error if .
+	// Pointer can be set to nil value, so we can remove CVSSRange entirely only
+	// if it's a pointer.
+	// The nil pointer is used in conjunction with the omitempty flag in the JSON tag,
+	// to remove the key completely in the payload.
 
 	// License Criteria
-	AllowUnknown           *bool     `json:"allow_unknown,omitempty"`
-	MultiLicensePermissive *bool     `json:"multi_license_permissive,omitempty"`
-	BannedLicenses         *[]string `json:"banned_licenses,omitempty"`
-	AllowedLicenses        *[]string `json:"allowed_licenses,omitempty"`
+	AllowUnknown           *bool    `json:"allow_unknown,omitempty"`            // Omitempty is used because the empty field is conflicting with MultiLicensePermissive
+	MultiLicensePermissive *bool    `json:"multi_license_permissive,omitempty"` // Omitempty is used because the empty field is conflicting with AllowUnknown
+	BannedLicenses         []string `json:"banned_licenses,omitempty"`
+	AllowedLicenses        []string `json:"allowed_licenses,omitempty"`
 }
 
 type BlockDownloadSettings struct {
-	Unscanned *bool `json:"unscanned,omitempty"`
-	Active    *bool `json:"active,omitempty"`
+	Unscanned bool `json:"unscanned"`
+	Active    bool `json:"active"`
 }
 
 type PolicyRuleActions struct {
-	Webhooks                *[]string              `json:"webhooks,omitempty"`
-	Mails                   *[]string              `json:"mails,omitempty"`
-	FailBuild               *bool                  `json:"fail_build,omitempty"`
-	BlockDownload           *BlockDownloadSettings `json:"block_download,omitempty"`
-	BlockReleaseBundle      *bool                  `json:"block_release_bundle_distribution,omitempty"`
-	NotifyWatchRecipients   *bool                  `json:"notify_watch_recipients,omitempty"`
-	NotifyDeployer          *bool                  `json:"notify_deployer,omitempty"`
-	CreateJiraTicketEnabled *bool                  `json:"create_ticket_enabled,omitempty"`
-	FailureGracePeriodDays  *int                   `json:"build_failure_grace_period_in_days,omitempty"`
+	Webhooks                []string              `json:"webhooks"`
+	Mails                   []string              `json:"mails"`
+	FailBuild               bool                  `json:"fail_build"`
+	BlockDownload           BlockDownloadSettings `json:"block_download"`
+	BlockReleaseBundle      bool                  `json:"block_release_bundle_distribution"`
+	NotifyWatchRecipients   bool                  `json:"notify_watch_recipients"`
+	NotifyDeployer          bool                  `json:"notify_deployer"`
+	CreateJiraTicketEnabled bool                  `json:"create_ticket_enabled"`
+	FailureGracePeriodDays  int                   `json:"build_failure_grace_period_in_days"`
 	// License Actions
-	CustomSeverity *string `json:"custom_severity,omitempty"`
+	CustomSeverity string `json:"custom_severity"`
 }
 
 type PolicyRule struct {
-	Name     *string             `json:"name,omitempty"`
-	Priority *int                `json:"priority,omitempty"`
-	Criteria *PolicyRuleCriteria `json:"criteria,omitempty"`
-	Actions  *PolicyRuleActions  `json:"actions,omitempty"`
+	Name     string              `json:"name"`
+	Priority int                 `json:"priority"`
+	Criteria *PolicyRuleCriteria `json:"criteria"`
+	Actions  PolicyRuleActions   `json:"actions"`
 }
 
 type Policy struct {
-	Name        *string       `json:"name,omitempty"`
-	Type        *string       `json:"type,omitempty"`
-	Author      *string       `json:"author,omitempty"`
-	Description *string       `json:"description,omitempty"`
-	Rules       *[]PolicyRule `json:"rules,omitempty"`
-	Created     *string       `json:"created,omitempty"`
-	Modified    *string       `json:"modified,omitempty"`
+	Name        string        `json:"name"`
+	Type        string        `json:"type"`
+	Author      string        `json:"author,omitempty"` // Omitempty is used because the field is computed
+	Description string        `json:"description"`
+	Rules       *[]PolicyRule `json:"rules"`
+	Created     string        `json:"created,omitempty"`  // Omitempty is used because the field is computed
+	Modified    string        `json:"modified,omitempty"` // Omitempty is used because the field is computed
 }
 
-func expandPolicy(d *schema.ResourceData) (*Policy, error) {
+func unpackPolicy(d *schema.ResourceData) (*Policy, error) {
 	policy := new(Policy)
 
-	policy.Name = StringPtr(d.Get("name").(string))
+	policy.Name = d.Get("name").(string)
 	if v, ok := d.GetOk("type"); ok {
-		policy.Type = StringPtr(v.(string))
+		policy.Type = v.(string)
 	}
 	if v, ok := d.GetOk("description"); ok {
-		policy.Description = StringPtr(v.(string))
+		policy.Description = v.(string)
 	}
 	if v, ok := d.GetOk("author"); ok {
-		policy.Author = StringPtr(v.(string))
+		policy.Author = v.(string)
 	}
-	policyRules, err := expandRules(d.Get("rules").([]interface{}), policy.Type)
+	policyRules, err := unpackRules(d.Get("rule").([]interface{}), policy.Type)
 	policy.Rules = &policyRules
 
 	return policy, err
 }
 
-func expandRules(configured []interface{}, policyType *string) (policyRules []PolicyRule, err error) {
-	rules := make([]PolicyRule, 0, len(configured))
+func unpackRules(configured []interface{}, policyType string) (policyRules []PolicyRule, err error) {
+	var rules []PolicyRule
 
-	for _, raw := range configured {
-		rule := new(PolicyRule)
-		data := raw.(map[string]interface{})
-		rule.Name = StringPtr(data["name"].(string))
-		rule.Priority = IntPtr(data["priority"].(int))
-		if *policyType == "license" {
-			rule.Criteria, err = expandLicenseCriteria(data["criteria"].([]interface{}))
-		}
-		if *policyType == "security" {
-			rule.Criteria, err = expandSecurityCriteria(data["criteria"].([]interface{}))
-		}
+	if configured != nil {
+		for _, raw := range configured {
+			rule := new(PolicyRule)
+			data := raw.(map[string]interface{})
+			rule.Name = data["name"].(string)
+			rule.Priority = data["priority"].(int)
 
-		if v, ok := data["actions"]; ok {
-			rule.Actions = expandActions(v.([]interface{}))
+			rule.Criteria, err = unpackCriteria(data["criteria"].(*schema.Set), policyType)
+			if v, ok := data["actions"]; ok {
+				rule.Actions = unpackActions(v.(*schema.Set))
+			}
+			rules = append(rules, *rule)
 		}
-		rules = append(rules, *rule)
 	}
 
 	return rules, err
 }
 
-func expandLicenseCriteria(l []interface{}) (*PolicyRuleCriteria, error) {
-	if len(l) == 0 {
+func unpackCriteria(d *schema.Set, policyType string) (*PolicyRuleCriteria, error) {
+	tfCriteria := d.List()
+	if len(tfCriteria) == 0 {
 		return nil, nil
 	}
-	m := l[0].(map[string]interface{}) // We made this a list of one to make schema validation easier
-	criteria := new(PolicyRuleCriteria)
-	if (m["allow_unknown"]) != nil {
-		criteria.AllowUnknown = BoolPtr(m["allow_unknown"].(bool))
-	}
-	if (m["banned_licenses"]) != nil {
-		criteria.BannedLicenses = expandLicenses(m["banned_licenses"].([]interface{}))
-	}
-	if (m["allowed_licenses"]) != nil {
-		criteria.AllowedLicenses = expandLicenses(m["allowed_licenses"].([]interface{}))
-	}
-	if (m["multi_license_permissive"]) != nil {
-		criteria.MultiLicensePermissive = BoolPtr(m["multi_license_permissive"].(bool))
-	}
 
-	return criteria, nil
-}
-
-func expandSecurityCriteria(l []interface{}) (*PolicyRuleCriteria, error) {
-	if len(l) == 0 {
-		return nil, nil
-	}
-	m := l[0].(map[string]interface{}) // We made this a list of one to make schema validation easier
+	m := tfCriteria[0].(map[string]interface{}) // We made this a list of one to make schema validation easier
 	criteria := new(PolicyRuleCriteria)
+	// The API doesn't allow both severity and license criteria to be _set_, even if they have empty values
+	// So we have to figure out which group is actually empty and not even set it
+	if policyType == "license" {
+		if v, ok := m["allow_unknown"]; ok {
+			criteria.AllowUnknown = BoolPtr(v.(bool))
+		}
+		if v, ok := m["banned_licenses"]; ok {
+			criteria.BannedLicenses = unpackLicenses(v.(*schema.Set))
+		}
+		if v, ok := m["allowed_licenses"]; ok {
+			criteria.AllowedLicenses = unpackLicenses(v.(*schema.Set))
+		}
+		if v, ok := m["multi_license_permissive"]; ok {
+			criteria.MultiLicensePermissive = BoolPtr(v.(bool))
+		}
+	} else {
+		minSev := m["min_severity"].(string)
+		cvss := unpackCVSSRange(m["cvss_range"].([]interface{}))
 
-	if (m["min_severity"]) != nil {
-		criteria.MinimumSeverity = m["min_severity"].(string)
-	}
-	if (m["cvss_range"]) != nil {
-		criteria.CVSSRange = expandCVSSRange(m["cvss_range"].([]interface{}))
+		// This is also picky about not allowing empty values to be set
+		if cvss == nil {
+			criteria.MinimumSeverity = minSev
+		} else {
+			criteria.CVSSRange = cvss
+		}
 	}
 	return criteria, nil
 }
 
-func expandCVSSRange(l []interface{}) *PolicyCVSSRange {
+func unpackCVSSRange(l []interface{}) *PolicyCVSSRange {
 	if len(l) == 0 {
 		return nil
 	}
 
 	m := l[0].(map[string]interface{})
 	cvssrange := &PolicyCVSSRange{
-		From: m["from"].(float64),
-		To:   m["to"].(float64),
+		From: Float64Ptr(m["from"].(float64)),
+		To:   Float64Ptr(m["to"].(float64)),
 	}
 	return cvssrange
 }
 
-func expandLicenses(l []interface{}) *[]string {
-	if len(l) == 0 {
-		return nil
-	}
-
-	licenses := make([]string, 0, len(l))
-	for _, license := range l {
+func unpackLicenses(d *schema.Set) []string {
+	var licenses []string
+	for _, license := range d.List() {
 		licenses = append(licenses, license.(string))
 	}
-	return &licenses
+	return licenses
 }
 
-func expandActions(l []interface{}) *PolicyRuleActions {
-	if len(l) == 0 {
-		return nil
-	}
+func unpackActions(l *schema.Set) PolicyRuleActions {
+	actions := PolicyRuleActions{}
+	policyActions := l.List()
+	m := policyActions[0].(map[string]interface{}) // We made this a list of one to make schema validation easier
 
-	actions := new(PolicyRuleActions)
-	m := l[0].(map[string]interface{}) // We made this a list of one to make schema validation easier
-	if v, ok := m["webhooks"]; ok && len(v.([]interface{})) > 0 {
-		m := v.([]interface{})
-		webhooks := make([]string, 0, len(m))
+	if v, ok := m["webhooks"]; ok {
+		m := v.(*schema.Set).List()
+		var webhooks []string
 		for _, hook := range m {
 			webhooks = append(webhooks, hook.(string))
 		}
-		actions.Webhooks = &webhooks // if webhook in not set - the empty value is not passing to the payload
+		actions.Webhooks = webhooks
 	}
-	if v, ok := m["mails"]; ok && len(v.([]interface{})) > 0 {
-		m := v.([]interface{})
-		mails := make([]string, 0, len(m))
+	if v, ok := m["mails"]; ok {
+		m := v.(*schema.Set).List()
+		var mails []string
 		for _, mail := range m {
 			mails = append(mails, mail.(string))
 		}
-		actions.Mails = &mails
+		actions.Mails = mails
 	}
 	if v, ok := m["fail_build"]; ok {
-		actions.FailBuild = BoolPtr(v.(bool))
+		actions.FailBuild = v.(bool)
 	}
 
 	if v, ok := m["block_download"]; ok {
-		if len(v.([]interface{})) > 0 {
-			vList := v.([]interface{})
+		if len(v.(*schema.Set).List()) > 0 {
+			vList := v.(*schema.Set).List()
 			vMap := vList[0].(map[string]interface{})
 
-			actions.BlockDownload = &BlockDownloadSettings{
-				Unscanned: BoolPtr(vMap["unscanned"].(bool)),
-				Active:    BoolPtr(vMap["active"].(bool)),
+			actions.BlockDownload = BlockDownloadSettings{
+				Unscanned: vMap["unscanned"].(bool),
+				Active:    vMap["active"].(bool),
 			}
 		} else {
-			actions.BlockDownload = &BlockDownloadSettings{
-				Unscanned: BoolPtr(false),
-				Active:    BoolPtr(false),
+			actions.BlockDownload = BlockDownloadSettings{
+				Unscanned: false,
+				Active:    false,
 			}
 			// Setting this false/false block feels like it _should_ work, since putting a false/false block in the terraform resource works fine
 			// However, it doesn't, and we end up getting this diff when running acceptance tests when this is optional in the schema
-			// rules.0.actions.0.block_download.#:           "1" => "0"
-			// rules.0.actions.0.block_download.0.active:    "false" => ""
-			// rules.0.actions.0.block_download.0.unscanned: "false" => ""
+			// rule.0.actions.0.block_download.#:           "1" => "0"
+			// rule.0.actions.0.block_download.0.active:    "false" => ""
+			// rule.0.actions.0.block_download.0.unscanned: "false" => ""
 		}
 	}
 	if v, ok := m["block_release_bundle_distribution"]; ok {
-		actions.BlockReleaseBundle = BoolPtr(v.(bool)) // TODO: why do we need to return the poiner instead of just assigning the value?
+		actions.BlockReleaseBundle = v.(bool)
 	}
-	//
+
 	if v, ok := m["notify_watch_recipients"]; ok {
-		actions.NotifyWatchRecipients = BoolPtr(v.(bool))
+		actions.NotifyWatchRecipients = v.(bool)
 	}
 	if v, ok := m["block_release_bundle_distribution"]; ok {
-		actions.BlockReleaseBundle = BoolPtr(v.(bool))
+		actions.BlockReleaseBundle = v.(bool)
 	}
 	if v, ok := m["notify_deployer"]; ok {
-		actions.NotifyDeployer = BoolPtr(v.(bool))
+		actions.NotifyDeployer = v.(bool)
 	}
 	if v, ok := m["create_ticket_enabled"]; ok {
-		actions.CreateJiraTicketEnabled = BoolPtr(v.(bool))
+		actions.CreateJiraTicketEnabled = v.(bool)
 	}
 	if v, ok := m["build_failure_grace_period_in_days"]; ok {
-		actions.FailureGracePeriodDays = IntPtr(v.(int))
+		actions.FailureGracePeriodDays = v.(int)
 	}
 	if v, ok := m["custom_severity"]; ok {
-		gosucks := v.(string)
-		actions.CustomSeverity = &gosucks
+		actions.CustomSeverity = v.(string)
 	}
 
 	return actions
 }
 
-func flattenLicenseRules(rules []PolicyRule) []interface{} {
-	l := make([]interface{}, len(rules))
+func packRules(rules []PolicyRule, policyType string) []interface{} {
+	var l []interface{}
 
-	for i, rule := range rules {
-		m := map[string]interface{}{
-			"name":     *rule.Name,
-			"priority": *rule.Priority,
-			"criteria": flattenLicenseCriteria(rule.Criteria),
-			"actions":  flattenActions(rule.Actions),
-		}
-		l[i] = m
-	}
+	for _, rule := range rules {
+		var criteria []interface{}
+		var isLicense bool
 
-	return l
-}
-
-func flattenSecurityRules(rules []PolicyRule) []interface{} {
-	l := make([]interface{}, len(rules))
+		switch policyType {
+		case "license":
+			criteria = packLicenseCriteria(rule.Criteria)
+			isLicense = true
+		case "security":
+			criteria = packSecurityCriteria(rule.Criteria)
+			isLicense = false
+		}
 
-	for i, rule := range rules {
 		m := map[string]interface{}{
-			"name":     *rule.Name,
-			"priority": *rule.Priority,
-			"criteria": flattenSecurityCriteria(rule.Criteria),
-			"actions":  flattenActions(rule.Actions),
+			"name":     rule.Name,
+			"priority": rule.Priority,
+			"criteria": criteria,
+			"actions":  packActions(rule.Actions, isLicense),
 		}
-		l[i] = m
+
+		l = append(l, m)
 	}
 
 	return l
 }
 
-func flattenLicenseCriteria(criteria *PolicyRuleCriteria) []interface{} {
-	if criteria == nil {
-		return []interface{}{}
-	}
+func packLicenseCriteria(criteria *PolicyRuleCriteria) []interface{} {
+
 	m := map[string]interface{}{}
 
 	if criteria.BannedLicenses != nil {
-		m["banned_licenses"] = *criteria.BannedLicenses
+		m["banned_licenses"] = criteria.BannedLicenses
 	}
 	if criteria.AllowedLicenses != nil {
-		m["allowed_licenses"] = *criteria.AllowedLicenses
-	}
-	if criteria.AllowUnknown != nil {
-		m["allow_unknown"] = *criteria.AllowUnknown // Same typo in the library
-	}
-	if criteria.MultiLicensePermissive != nil {
-		m["multi_license_permissive"] = *criteria.MultiLicensePermissive
+		m["allowed_licenses"] = criteria.AllowedLicenses
 	}
+	m["allow_unknown"] = criteria.AllowUnknown
+	m["multi_license_permissive"] = criteria.MultiLicensePermissive
 
 	return []interface{}{m}
 }
 
-func flattenSecurityCriteria(criteria *PolicyRuleCriteria) []interface{} {
-	if criteria == nil {
-		return []interface{}{}
-	}
+func packSecurityCriteria(criteria *PolicyRuleCriteria) []interface{} {
 	m := map[string]interface{}{}
-
-	if criteria.CVSSRange != nil {
-		m["cvss_range"] = flattenCVSSRange(criteria.CVSSRange)
-	}
+	// cvss_range and min_severity are conflicting, only one can be present in the JSON
+	m["cvss_range"] = packCVSSRange(criteria.CVSSRange)
 	m["min_severity"] = criteria.MinimumSeverity
 
 	return []interface{}{m}
 }
 
-func flattenCVSSRange(cvss *PolicyCVSSRange) []interface{} {
+func packCVSSRange(cvss *PolicyCVSSRange) []interface{} {
 	if cvss == nil {
 		return []interface{}{}
 	}
-
 	m := map[string]interface{}{
-		"from": cvss.From,
-		"to":   cvss.To,
+		"from": *cvss.From,
+		"to":   *cvss.To,
 	}
 	return []interface{}{m}
 }
 
-func flattenActions(actions *PolicyRuleActions) []interface{} {
-	if actions == nil {
-		return []interface{}{}
-	}
+func packActions(actions PolicyRuleActions, license bool) []interface{} {
 
 	m := map[string]interface{}{
-		"block_download": flattenBlockDownload(actions.BlockDownload),
-	}
-	if actions.Webhooks != nil {
-		m["webhooks"] = *actions.Webhooks
-	}
-	if actions.Mails != nil {
-		m["mails"] = *actions.Mails
-	}
-	if actions.FailBuild != nil {
-		m["fail_build"] = *actions.FailBuild
-	}
-	if actions.BlockReleaseBundle != nil {
-		m["block_release_bundle_distribution"] = *actions.BlockReleaseBundle
+		"block_download":                     packBlockDownload(actions.BlockDownload),
+		"webhooks":                           actions.Webhooks,
+		"mails":                              actions.Mails,
+		"fail_build":                         actions.FailBuild,
+		"block_release_bundle_distribution":  actions.BlockReleaseBundle,
+		"notify_watch_recipients":            actions.NotifyWatchRecipients,
+		"notify_deployer":                    actions.NotifyDeployer,
+		"create_ticket_enabled":              actions.CreateJiraTicketEnabled,
+		"build_failure_grace_period_in_days": actions.FailureGracePeriodDays,
 	}
-	if actions.NotifyWatchRecipients != nil {
-		m["notify_watch_recipients"] = *actions.NotifyWatchRecipients
-	}
-	if actions.NotifyDeployer != nil {
-		m["notify_deployer"] = *actions.NotifyDeployer
-	}
-	if actions.CreateJiraTicketEnabled != nil {
-		m["create_ticket_enabled"] = *actions.CreateJiraTicketEnabled
-	}
-	if actions.FailureGracePeriodDays != nil {
-		m["build_failure_grace_period_in_days"] = *actions.FailureGracePeriodDays // integer
-	}
-	if actions.CustomSeverity != nil {
-		m["custom_severity"] = *actions.CustomSeverity
+
+	if license {
+		m["custom_severity"] = actions.CustomSeverity
 	}
 
 	return []interface{}{m}
 }
 
-func flattenBlockDownload(bd *BlockDownloadSettings) []interface{} {
-	if bd == nil {
-		return []interface{}{}
-	}
+func packBlockDownload(bd BlockDownloadSettings) []interface{} {
 
 	m := map[string]interface{}{}
-	if bd.Unscanned != nil {
-		m["unscanned"] = *bd.Unscanned
-	}
-	if bd.Active != nil {
-		m["active"] = *bd.Active
-	}
-
+	m["unscanned"] = bd.Unscanned
+	m["active"] = bd.Active
 	return []interface{}{m}
 }
 
-// Create Xray policy
 func resourceXrayPolicyCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
-	policy, err := expandPolicy(d)
+	policy, err := unpackPolicy(d)
 	// Warning or errors can be collected in a slice type
-	var diags diag.Diagnostics
 	if err != nil {
 		return diag.FromErr(err)
 	}
@@ -396,12 +346,10 @@ func resourceXrayPolicyCreate(ctx context.Context, d *schema.ResourceData, m int
 		return diag.FromErr(err)
 	}
 
-	d.SetId(*policy.Name)
-	resourceXrayPolicyRead(ctx, d, m)
-	return diags
+	d.SetId(policy.Name)
+	return resourceXrayPolicyRead(ctx, d, m)
 }
 
-// Get Xray policy by name
 func getPolicy(id string, client *resty.Client) (Policy, *resty.Response, error) {
 	policy := Policy{}
 	resp, err := client.R().SetResult(&policy).Get("xray/api/v2/policies/" + id)
@@ -409,12 +357,10 @@ func getPolicy(id string, client *resty.Client) (Policy, *resty.Response, error)
 }
 func resourceXrayPolicyRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
 	policy, resp, err := getPolicy(d.Id(), m.(*resty.Client))
-	var diags diag.Diagnostics
 	if err != nil {
 		if resp != nil && resp.StatusCode() == http.StatusNotFound {
 			log.Printf("[WARN] Xray policy (%s) not found, removing from state", d.Id())
 			d.SetId("")
-			return nil
 		}
 		return diag.FromErr(err)
 	}
@@ -425,7 +371,7 @@ func resourceXrayPolicyRead(ctx context.Context, d *schema.ResourceData, m inter
 	if err := d.Set("type", policy.Type); err != nil {
 		return diag.FromErr(err)
 	}
-	if policy.Description != nil {
+	if len(policy.Description) > 0 {
 		if err := d.Set("description", policy.Description); err != nil {
 			return diag.FromErr(err)
 		}
@@ -439,21 +385,15 @@ func resourceXrayPolicyRead(ctx context.Context, d *schema.ResourceData, m inter
 	if err := d.Set("modified", policy.Modified); err != nil {
 		return diag.FromErr(err)
 	}
-	if *policy.Type == "license" {
-		if err := d.Set("rules", flattenLicenseRules(*policy.Rules)); err != nil {
-			return diag.FromErr(err)
-		}
-	}
-	if *policy.Type == "security" {
-		if err := d.Set("rules", flattenSecurityRules(*policy.Rules)); err != nil {
-			return diag.FromErr(err)
-		}
+	if err := d.Set("rule", packRules(*policy.Rules, policy.Type)); err != nil {
+		return diag.FromErr(err)
 	}
-	return diags
+
+	return nil
 }
 
 func resourceXrayPolicyUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
-	policy, err := expandPolicy(d)
+	policy, err := unpackPolicy(d)
 	if err != nil {
 		return diag.FromErr(err)
 	}
@@ -462,16 +402,16 @@ func resourceXrayPolicyUpdate(ctx context.Context, d *schema.ResourceData, m int
 		return diag.FromErr(err)
 	}
 
-	d.SetId(*policy.Name)
+	d.SetId(policy.Name)
 	return resourceXrayPolicyRead(ctx, d, m)
 }
 
 func resourceXrayPolicyDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
 	// Warning or errors can be collected in a slice type
-	var diags diag.Diagnostics
-	_, err := m.(*resty.Client).R().Delete("xray/api/v2/policies/" + d.Id())
-	if err != nil {
+	resp, err := m.(*resty.Client).R().Delete("xray/api/v2/policies/" + d.Id())
+	if err != nil && resp.StatusCode() == http.StatusInternalServerError {
+		d.SetId("")
 		return diag.FromErr(err)
 	}
-	return diags
+	return nil
 }
diff --git a/pkg/xray/provider.go b/pkg/xray/provider.go
index 621b047d..75eb508e 100644
--- a/pkg/xray/provider.go
+++ b/pkg/xray/provider.go
@@ -1,12 +1,16 @@
 package xray
 
 import (
+	"context"
 	"fmt"
+	"net/http"
+	"net/url"
+	"strings"
+
 	"github.com/go-resty/resty/v2"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
-	"net/http"
-	"net/url"
 )
 
 // Version for some reason isn't getting updated by the linker
@@ -20,17 +24,18 @@ func Provider() *schema.Provider {
 			"url": {
 				Type:     schema.TypeString,
 				Optional: true,
-				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"JFROG_URL", "ARTIFACTORY_URL", "PROJECTS_URL"},
+				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"JFROG_URL", "XRAY_URL"},
 					"http://localhost:8081"),
 				ValidateFunc: validation.IsURLWithHTTPorHTTPS,
+				Description:  "URL of Artifactory. This can also be sourced from the `XRAY_URL` or `JFROG_URL` environment variable. Default to 'http://localhost:8081' if not set.",
 			},
 			"access_token": {
-				Type:      schema.TypeString,
-				Optional:  true,
-				Sensitive: true,
-				DefaultFunc: schema.MultiEnvDefaultFunc([]string{"XRAY_ACCESS_TOKEN", "ARTIFACTORY_ACCESS_TOKEN"},
-					"JFROG_ACCESS_TOKEN"),
-				Description: "This is a bearer token that can be given to you by your admin under `Identity and Access`",
+				Type:             schema.TypeString,
+				Optional:         true,
+				Sensitive:        true,
+				DefaultFunc:      schema.MultiEnvDefaultFunc([]string{"XRAY_ACCESS_TOKEN", "JFROG_ACCESS_TOKEN"}, ""),
+				ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
+				Description:      "This is a bearer token that can be given to you by your admin under `Identity and Access`",
 			},
 		},
 
@@ -38,15 +43,17 @@ func Provider() *schema.Provider {
 			// Xray resources
 			"xray_security_policy": resourceXraySecurityPolicyV2(),
 			"xray_license_policy":  resourceXrayLicensePolicyV2(),
+			"xray_watch":           resourceXrayWatch(),
 		},
 	}
 
-	p.ConfigureFunc = func(d *schema.ResourceData) (interface{}, error) {
+	p.ConfigureContextFunc = func(ctx context.Context, data *schema.ResourceData) (interface{}, diag.Diagnostics) {
 		terraformVersion := p.TerraformVersion
 		if terraformVersion == "" {
-			terraformVersion = "0.11+compatible"
+			terraformVersion = "0.13+compatible"
 		}
-		return providerConfigure(d, terraformVersion)
+		configuration, err := providerConfigure(data, terraformVersion)
+		return configuration, diag.FromErr(err)
 	}
 
 	return p
@@ -102,8 +109,13 @@ func providerConfigure(d *schema.ResourceData, terraformVersion string) (interfa
 	if err != nil {
 		return nil, err
 	}
+
 	_, err = sendUsageRepo(restyBase, terraformVersion)
+	if err != nil {
+		return nil, err
+	}
 
+	err = checkArtifactoryLicense(restyBase)
 	if err != nil {
 		return nil, err
 	}
@@ -133,3 +145,24 @@ func sendUsageRepo(restyBase *resty.Client, terraformVersion string) (interface{
 	}
 	return nil, nil
 }
+
+func checkArtifactoryLicense(client *resty.Client) error {
+
+	type License struct {
+		Type         string `json:"type"`
+		ValidThrough string `json:"validThrough"`
+		LicensedTo   string `json:"licensedTo"`
+	}
+
+	license := License{}
+	_, err := client.R().SetResult(&license).Get("/artifactory/api/system/licenses/")
+	if err != nil {
+		return err
+	}
+
+	if !strings.Contains(license.Type, "Enterprise") {
+		return fmt.Errorf("Artifactory requires Enterprise license to work with Terraform!")
+	}
+
+	return nil
+}
diff --git a/pkg/xray/resource_xray_license_policy.go b/pkg/xray/resource_xray_license_policy.go
index 5effebb7..e802f30d 100644
--- a/pkg/xray/resource_xray_license_policy.go
+++ b/pkg/xray/resource_xray_license_policy.go
@@ -2,6 +2,7 @@ package xray
 
 import (
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
 )
 
 func resourceXrayLicensePolicyV2() *schema.Resource {
@@ -20,143 +21,179 @@ func resourceXrayLicensePolicyV2() *schema.Resource {
 
 		Schema: map[string]*schema.Schema{
 			"name": {
-				Type:     schema.TypeString,
-				Required: true,
-				ForceNew: true,
+				Type:             schema.TypeString,
+				Required:         true,
+				ForceNew:         true,
+				Description:      "Name of the policy (must be unique)",
+				ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
 			},
 			"description": {
-				Type:     schema.TypeString,
-				Optional: true,
+				Type:        schema.TypeString,
+				Optional:    true,
+				Description: "More verbose description of the policy",
 			},
 			"type": {
-				Type:     schema.TypeString,
-				Required: true,
+				Type:             schema.TypeString,
+				Required:         true,
+				Description:      "Type of the policy",
+				ValidateDiagFunc: inList("Security", "License"),
 			},
 			"author": {
-				Type:     schema.TypeString,
-				Computed: true,
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: "User, who created the policy",
 			},
 			"created": {
-				Type:     schema.TypeString,
-				Computed: true,
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: "Creation timestamp",
 			},
 			"modified": {
-				Type:     schema.TypeString,
-				Computed: true,
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: "Modification timestamp",
 			},
-			"rules": {
-				Type:     schema.TypeList,
-				Required: true,
+			"rule": {
+				Type:        schema.TypeList,
+				Required:    true,
+				Description: "Nested block describing a policy rule. Described below",
 				Elem: &schema.Resource{
 					Schema: map[string]*schema.Schema{
 						"name": {
-							Type:     schema.TypeString,
-							Required: true,
+							Type:             schema.TypeString,
+							Required:         true,
+							Description:      "Name of the rule",
+							ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
 						},
 						"priority": {
-							Type:     schema.TypeInt,
-							Required: true,
+							Type:             schema.TypeInt,
+							Required:         true,
+							ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(1)),
+							Description:      "Integer describing the rule priority. Must be at least 1",
 						},
 						"criteria": {
-							Type:     schema.TypeList,
-							Required: true,
-							MinItems: 1,
-							MaxItems: 1,
+							Type:        schema.TypeSet,
+							Required:    true,
+							Description: "Nested block describing the criteria for the policy. Described below",
+							MinItems:    1,
 							Elem: &schema.Resource{
 								Schema: map[string]*schema.Schema{
 									"banned_licenses": {
-										Type:     schema.TypeList,
-										Optional: true,
+										Type:        schema.TypeSet,
+										Optional:    true,
+										Description: "A list of OSS license names that may not be attached to a component.",
 										Elem: &schema.Schema{
-											Type: schema.TypeString,
+											Type:         schema.TypeString,
+											ValidateFunc: licenseTypeValidator,
 										},
 									},
 									"allowed_licenses": {
-										Type:     schema.TypeList,
-										Optional: true,
+										Type:        schema.TypeSet,
+										Optional:    true,
+										Description: "A list of OSS license names that may be attached to a component.",
 										Elem: &schema.Schema{
-											Type: schema.TypeString,
+											Type:         schema.TypeString,
+											ValidateFunc: licenseTypeValidator,
 										},
 									},
 									"allow_unknown": {
-										Type:     schema.TypeBool,
-										Optional: true,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Default:     true,
+										Description: "A violation will be generated for artifacts with unknown licenses (`true` or `false`).",
 									},
 									"multi_license_permissive": {
-										Type:     schema.TypeBool,
-										Optional: true,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Default:     false,
+										Description: "Do not generate a violation if at least one license is valid in cases whereby multiple licenses were detected on the component",
 									},
 								},
 							},
 						},
 						"actions": {
-							Type:     schema.TypeList,
-							Optional: true,
-							MaxItems: 1,
+							Type:        schema.TypeSet,
+							Optional:    true,
+							Description: "Nested block describing the actions to be applied by the policy. Described below.",
+							MaxItems:    1,
 							Elem: &schema.Resource{
 								Schema: map[string]*schema.Schema{
 									"webhooks": {
-										Type:     schema.TypeList,
-										Optional: true,
+										Type:        schema.TypeSet,
+										Optional:    true,
+										Description: "A list of Xray-configured webhook URLs to be invoked if a violation is triggered.",
 										Elem: &schema.Schema{
 											Type: schema.TypeString,
 										},
 									},
 									"mails": {
-										Type:     schema.TypeList,
-										Optional: true,
+										Type:        schema.TypeSet,
+										Optional:    true,
+										Description: "A list of email addressed that will get emailed when a violation is triggered.",
 										Elem: &schema.Schema{
 											Type:         schema.TypeString,
 											ValidateFunc: validateIsEmail,
 										},
 									},
 									"block_download": {
-										Type:     schema.TypeList,
-										Required: true,
-										MaxItems: 1,
+										Type:        schema.TypeSet,
+										Required:    true,
+										Description: "Nested block describing artifacts that should be blocked for download if a violation is triggered. Described below.",
+										MaxItems:    1,
 										Elem: &schema.Resource{
 											Schema: map[string]*schema.Schema{
 												"unscanned": {
-													Type:     schema.TypeBool,
-													Required: true,
+													Type:        schema.TypeBool,
+													Required:    true,
+													Description: " Whether or not to block download of artifacts that meet the artifact `filters` for the associated `xray_watch` resource but have not been scanned yet.",
 												},
 												"active": {
-													Type:     schema.TypeBool,
-													Required: true,
+													Type:        schema.TypeBool,
+													Required:    true,
+													Description: "Whether or not to block download of artifacts that meet the artifact and severity `filters` for the associated `xray_watch` resource.",
 												},
 											},
 										},
 									},
 									"block_release_bundle_distribution": {
-										Type:     schema.TypeBool,
-										Optional: true,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Description: "Blocks Release Bundle distribution to Edge nodes if a violation is found.",
 									},
 									"fail_build": {
-										Type:     schema.TypeBool,
-										Optional: true,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Description: "Whether or not the related CI build should be marked as failed if a violation is triggered. This option is only available when the policy is applied to an `xray_watch` resource with a `type` of `builds`.",
 									},
 									"notify_deployer": {
-										Type:     schema.TypeBool,
-										Optional: true,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Description: "Sends an email message to component deployer with details about the generated Violations.",
 									},
 									"notify_watch_recipients": {
-										Type:     schema.TypeBool,
-										Optional: true,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Description: "Sends an email message to all configured recipients inside a specific watch with details about the generated Violations.",
 									},
 									"create_ticket_enabled": {
-										Type:     schema.TypeBool,
-										Optional: true,
-										Default:  false,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Default:     false,
+										Description: "Create Jira Ticket for this Policy Violation. Requires configured Jira integration.",
 									},
 									"custom_severity": {
-										Type:     schema.TypeString,
-										Optional: true,
-										Default:  "High",
+										Type:             schema.TypeString,
+										Optional:         true,
+										Default:          "High",
+										Description:      "The severity of violation to be triggered if the `criteria` are met.",
+										ValidateDiagFunc: inList("Critical", "High", "Medium", "Low"),
 									},
 									"build_failure_grace_period_in_days": {
-										Type:     schema.TypeInt,
-										Optional: true,
-										Default:  3,
+										Type:             schema.TypeInt,
+										Optional:         true,
+										Description:      "Allow grace period for certain number of days. All violations will be ignored during this time. To be used only if `fail_build` is enabled.",
+										Default:          3,
+										ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(0)),
 									},
 								},
 							},
diff --git a/pkg/xray/resource_xray_security_policy.go b/pkg/xray/resource_xray_security_policy.go
index 9b1f3b7c..657e2436 100644
--- a/pkg/xray/resource_xray_security_policy.go
+++ b/pkg/xray/resource_xray_security_policy.go
@@ -2,6 +2,7 @@ package xray
 
 import (
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
 )
 
 func resourceXraySecurityPolicyV2() *schema.Resource {
@@ -20,69 +21,88 @@ func resourceXraySecurityPolicyV2() *schema.Resource {
 
 		Schema: map[string]*schema.Schema{
 			"name": {
-				Type:     schema.TypeString,
-				Required: true,
-				ForceNew: true,
+				Type:             schema.TypeString,
+				Required:         true,
+				ForceNew:         true,
+				Description:      "Name of the policy (must be unique)",
+				ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
 			},
 			"description": {
-				Type:     schema.TypeString,
-				Optional: true,
+				Type:        schema.TypeString,
+				Optional:    true,
+				Description: "More verbose description of the policy",
 			},
 			"type": {
-				Type:     schema.TypeString,
-				Required: true,
+				Type:             schema.TypeString,
+				Required:         true,
+				Description:      "Type of the policy",
+				ValidateDiagFunc: inList("Security", "License"),
 			},
-			// not in create policy body, but it is in the get call response.
 			"author": {
-				Type:     schema.TypeString,
-				Computed: true,
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: "User, who created the policy",
 			},
 			"created": {
-				Type:     schema.TypeString,
-				Computed: true,
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: "Creation timestamp",
 			},
 			"modified": {
-				Type:     schema.TypeString,
-				Computed: true,
+				Type:        schema.TypeString,
+				Computed:    true,
+				Description: "Modification timestamp",
 			},
-			//
-			"rules": {
-				Type:     schema.TypeList,
-				Required: true,
+			"rule": {
+				Type:        schema.TypeList,
+				Required:    true,
+				Description: "Nested block describing security rule. Described below",
 				Elem: &schema.Resource{
 					Schema: map[string]*schema.Schema{
 						"name": {
-							Type:     schema.TypeString,
-							Required: true,
+							Type:             schema.TypeString,
+							Required:         true,
+							Description:      "Name of the rule",
+							ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
 						},
 						"priority": {
-							Type:     schema.TypeInt,
-							Required: true,
+							Type:             schema.TypeInt,
+							Required:         true,
+							ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(1)),
+							Description:      "Integer describing the rule priority. Must be at least 1",
 						},
 						"criteria": {
-							Type:     schema.TypeList,
-							Required: true,
-							MinItems: 1,
-							MaxItems: 1,
+							Type:        schema.TypeSet,
+							Required:    true,
+							MinItems:    1,
+							MaxItems:    1,
+							Description: "Nested block describing the criteria for the policy. Described below.",
 							Elem: &schema.Resource{
 								Schema: map[string]*schema.Schema{
 									"min_severity": {
-										Type:     schema.TypeString,
-										Optional: true,
+										Type:             schema.TypeString,
+										Optional:         true,
+										Description:      "The minimum security vulnerability severity that will be impacted by the policy.",
+										ValidateDiagFunc: inList("All Severities", "Critical", "High", "Medium", "Low"),
 									},
 									"cvss_range": {
-										Type:     schema.TypeList,
-										Optional: true,
-										MaxItems: 1,
+										Type:        schema.TypeList,
+										Optional:    true,
+										MaxItems:    1,
+										Description: "Nested block describing a CVS score range to be impacted. Defined below.",
 										Elem: &schema.Resource{
 											Schema: map[string]*schema.Schema{
 												"from": {
-													Type:     schema.TypeFloat,
-													Required: true,
+													Type:             schema.TypeFloat,
+													Required:         true,
+													Description:      "The beginning of the range of CVS scores (from 1-10, float) to flag.",
+													ValidateDiagFunc: validation.ToDiagFunc(validation.FloatBetween(0, 10)),
 												},
 												"to": {
-													Type:     schema.TypeFloat,
-													Required: true,
+													Type:             schema.TypeFloat,
+													Required:         true,
+													Description:      "The end of the range of CVS scores (from 1-10, float) to flag. ",
+													ValidateDiagFunc: validation.ToDiagFunc(validation.FloatBetween(0, 10)),
 												},
 											},
 										},
@@ -91,72 +111,84 @@ func resourceXraySecurityPolicyV2() *schema.Resource {
 							},
 						},
 						"actions": {
-							Type:     schema.TypeList,
-							Optional: true,
-							MaxItems: 1,
+							Type:        schema.TypeSet,
+							Optional:    true,
+							MaxItems:    1,
+							Description: "Nested block describing the actions to be applied by the policy. Described below.",
 							Elem: &schema.Resource{
 								Schema: map[string]*schema.Schema{
 									"webhooks": {
-										Type:     schema.TypeList,
-										Optional: true,
+										Type:        schema.TypeSet,
+										Optional:    true,
+										Description: "A list of Xray-configured webhook URLs to be invoked if a violation is triggered.",
 										Elem: &schema.Schema{
 											Type: schema.TypeString,
 										},
 									},
 									"mails": {
-										Type:     schema.TypeList,
-										Optional: true,
+										Type:        schema.TypeSet,
+										Optional:    true,
+										Description: "A list of email addressed that will get emailed when a violation is triggered.",
 										Elem: &schema.Schema{
 											Type:         schema.TypeString,
 											ValidateFunc: validateIsEmail,
 										},
 									},
 									"block_download": {
-										Type:     schema.TypeList,
-										Required: true,
-										MaxItems: 1,
+										Type:        schema.TypeSet,
+										Required:    true,
+										MaxItems:    1,
+										Description: "Nested block describing artifacts that should be blocked for download if a violation is triggered. Described below.",
 										Elem: &schema.Resource{
 											Schema: map[string]*schema.Schema{
 												"unscanned": {
-													Type:     schema.TypeBool,
-													Required: true,
+													Type:        schema.TypeBool,
+													Required:    true,
+													Description: "Whether or not to block download of artifacts that meet the artifact `filters` for the associated `xray_watch` resource but have not been scanned yet.",
 												},
 												"active": {
-													Type:     schema.TypeBool,
-													Required: true,
+													Type:        schema.TypeBool,
+													Required:    true,
+													Description: "Whether or not to block download of artifacts that meet the artifact and severity `filters` for the associated `xray_watch` resource.",
 												},
 											},
 										},
 									},
 									"block_release_bundle_distribution": {
-										Type:     schema.TypeBool,
-										Optional: true,
-										Default:  true,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Default:     true,
+										Description: "Blocks Release Bundle distribution to Edge nodes if a violation is found.",
 									},
 									"fail_build": {
-										Type:     schema.TypeBool,
-										Optional: true,
-										Default:  true,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Default:     true,
+										Description: "Whether or not the related CI build should be marked as failed if a violation is triggered. This option is only available when the policy is applied to an `xray_watch` resource with a `type` of `builds`.",
 									},
 									"notify_deployer": {
-										Type:     schema.TypeBool,
-										Optional: true,
-										Default:  false,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Default:     false,
+										Description: "Sends an email message to component deployer with details about the generated Violations.",
 									},
 									"notify_watch_recipients": {
-										Type:     schema.TypeBool,
-										Optional: true,
-										Default:  false,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Default:     false,
+										Description: "Sends an email message to all configured recipients inside a specific watch with details about the generated Violations.",
 									},
 									"create_ticket_enabled": {
-										Type:     schema.TypeBool,
-										Optional: true,
-										Default:  false,
+										Type:        schema.TypeBool,
+										Optional:    true,
+										Default:     false,
+										Description: "Create Jira Ticket for this Policy Violation. Requires configured Jira integration.",
 									},
 									"build_failure_grace_period_in_days": {
-										Type:     schema.TypeInt,
-										Optional: true,
-										Default:  3,
+										Type:        schema.TypeInt,
+										Optional:    true,
+										Default:     3,
+										Description: "Allow grace period for certain number of days. All violations will be ignored during this time. To be used only if `fail_build` is enabled.",
 									},
 								},
 							},
diff --git a/pkg/xray/resource_xray_watch.go b/pkg/xray/resource_xray_watch.go
new file mode 100644
index 00000000..70574fd9
--- /dev/null
+++ b/pkg/xray/resource_xray_watch.go
@@ -0,0 +1,120 @@
+package xray
+
+import (
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+func resourceXrayWatch() *schema.Resource {
+	return &schema.Resource{
+		CreateContext: resourceXrayWatchCreate,
+		ReadContext:   resourceXrayWatchRead,
+		UpdateContext: resourceXrayWatchUpdate,
+		DeleteContext: resourceXrayWatchDelete,
+		Description:   "Provides an Xray watch resource.",
+
+		Importer: &schema.ResourceImporter{
+			StateContext: schema.ImportStatePassthroughContext,
+		},
+
+		Schema: map[string]*schema.Schema{
+			"name": {
+				Type:             schema.TypeString,
+				Required:         true,
+				ForceNew:         true,
+				Description:      "Name of the watch (must be unique)",
+				ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
+			},
+			"description": {
+				Type:        schema.TypeString,
+				Optional:    true,
+				Description: "Description of the watch",
+			},
+			"active": {
+				Type:        schema.TypeBool,
+				Optional:    true,
+				Description: "Whether or not the watch is active",
+			},
+			"watch_resource": {
+				Type:        schema.TypeSet,
+				Required:    true,
+				Description: "Nested argument describing the resources to be watched. Defined below.",
+				Elem: &schema.Resource{
+					Schema: map[string]*schema.Schema{
+						"type": {
+							Type:             schema.TypeString,
+							Required:         true,
+							Description:      "Type of resource to be watched. Options: `all-repos`, `repository`, `build`, `project`, `all-projects`.",
+							ValidateDiagFunc: inList("all-repos", "repository", "build", "project", "all-projects"),
+						},
+						"bin_mgr_id": {
+							Type:        schema.TypeString,
+							Optional:    true,
+							Default:     "default",
+							Description: "The ID number of a binary manager resource. Should be set to `default` if not set on the Artifactory side.",
+						},
+						"name": {
+							Type:        schema.TypeString,
+							Optional:    true,
+							Description: "The name of the build or repository. Enable Xray indexing must be enabled on the repo or build",
+						},
+						"filter": {
+							Type:        schema.TypeList,
+							Optional:    true,
+							Description: "Nested argument describing filters to be applied. Defined below.",
+							Elem: &schema.Resource{
+								Schema: map[string]*schema.Schema{
+									"type": {
+										Type:             schema.TypeString,
+										Required:         true,
+										Description:      "The type of filter, such as `regex`, `package-type` or `ant-patterns`",
+										ValidateDiagFunc: inList("regex", "package-type", "ant-patterns"),
+									},
+									// TODO support Exclude and Include patterns
+									// eg "value":{"ExcludePatterns":[],"IncludePatterns":["*"]}
+									"value": {
+										Type:             schema.TypeString,
+										Required:         true,
+										Description:      "The value of the filter, such as the text of the regex or name of the package type.",
+										ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+			// Key is "assigned_policies" in the API call body. Plural is used for better reflection of the
+			// actual functionality (see HCL examples)
+			"assigned_policy": {
+				Type:        schema.TypeSet,
+				Required:    true,
+				Description: "Nested argument describing policies that will be applied. Defined below.",
+				Elem: &schema.Resource{
+					Schema: map[string]*schema.Schema{
+						"name": {
+							Type:        schema.TypeString,
+							Required:    true,
+							Description: "The name of the policy that will be applied",
+						},
+						"type": {
+							Type:             schema.TypeString,
+							Required:         true,
+							Description:      "The type of the policy - security or license",
+							ValidateDiagFunc: inList("security", "license"),
+						},
+					},
+				},
+			},
+			"watch_recipients": {
+				Type:        schema.TypeSet,
+				Optional:    true,
+				Description: "A list of email addressed that will get emailed when a violation is triggered.",
+				Elem: &schema.Schema{
+					Type:         schema.TypeString,
+					ValidateFunc: validateIsEmail,
+				},
+			},
+		},
+	}
+}
diff --git a/pkg/xray/util.go b/pkg/xray/util.go
index b9d8fef7..9035922a 100644
--- a/pkg/xray/util.go
+++ b/pkg/xray/util.go
@@ -181,6 +181,10 @@ func sendConfigurationPatch(content []byte, m interface{}) error {
 	return err
 }
 
+var neverRetry = func(response *resty.Response, err error) bool {
+	return false
+}
+
 func BoolPtr(v bool) *bool { return &v }
 
 func IntPtr(v int) *int { return &v }
diff --git a/pkg/xray/validators.go b/pkg/xray/validators.go
index 43577eb3..5c742b4f 100644
--- a/pkg/xray/validators.go
+++ b/pkg/xray/validators.go
@@ -2,15 +2,16 @@ package xray
 
 import (
 	"fmt"
-	"github.com/gorhill/cronexpr"
-	"github.com/hashicorp/go-cty/cty"
-	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
-	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
 	"net/mail"
 	"os"
 	"regexp"
 	"strings"
 
+	"github.com/gorhill/cronexpr"
+	"github.com/hashicorp/go-cty/cty"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
 )
 
@@ -528,3 +529,7 @@ func minLength(length int) func(i interface{}, k string) ([]string, []error) {
 		return nil, nil
 	}
 }
+
+func inList(strings ...string) schema.SchemaValidateDiagFunc {
+	return validation.ToDiagFunc(validation.StringInSlice(strings, true))
+}
diff --git a/pkg/xray/watches.go b/pkg/xray/watches.go
new file mode 100644
index 00000000..e0cfbe85
--- /dev/null
+++ b/pkg/xray/watches.go
@@ -0,0 +1,246 @@
+package xray
+
+import (
+	"context"
+	"log"
+	"net/http"
+
+	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+
+	"github.com/go-resty/resty/v2"
+)
+
+type WatchGeneralData struct {
+	Name        string `json:"name"`
+	Description string `json:"description"`
+	Active      bool   `json:"active"`
+}
+
+type WatchFilterValue struct {
+	Key   string `json:"key"`
+	Value string `json:"value"`
+}
+
+type WatchFilter struct {
+	Type  string `json:"type"`
+	Value string `json:"value"`
+}
+
+type WatchProjectResource struct {
+	Type            string        `json:"type"`
+	BinaryManagerId string        `json:"bin_mgr_id"`
+	Filters         []WatchFilter `json:"filters"`
+	Name            string        `json:"name"`
+}
+
+type WatchProjectResources struct {
+	Resources []WatchProjectResource `json:"resources"`
+}
+
+type WatchAssignedPolicy struct {
+	Name string `json:"name"`
+	Type string `json:"type"`
+}
+
+type Watch struct {
+	GeneralData      WatchGeneralData      `json:"general_data"`
+	ProjectResources WatchProjectResources `json:"project_resources"`
+	AssignedPolicies []WatchAssignedPolicy `json:"assigned_policies"`
+	WatchRecipients  []string              `json:"watch_recipients"`
+}
+
+func unpackWatch(d *schema.ResourceData) Watch {
+	watch := Watch{}
+
+	gd := WatchGeneralData{
+		Name: d.Get("name").(string),
+	}
+	if v, ok := d.GetOk("description"); ok {
+		gd.Description = v.(string)
+	}
+	if v, ok := d.GetOk("active"); ok {
+		gd.Active = v.(bool)
+	}
+	watch.GeneralData = gd
+
+	pr := WatchProjectResources{}
+	if v, ok := d.GetOk("watch_resource"); ok {
+		var r []WatchProjectResource
+		for _, res := range v.(*schema.Set).List() {
+			r = append(r, unpackProjectResource(res))
+		}
+		pr.Resources = r
+	}
+	watch.ProjectResources = pr
+
+	var ap []WatchAssignedPolicy
+	if v, ok := d.GetOk("assigned_policy"); ok {
+		policies := v.(*schema.Set).List()
+		for _, pol := range policies {
+			ap = append(ap, unpackAssignedPolicy(pol))
+		}
+	}
+	watch.AssignedPolicies = ap
+
+	var watchRecipients []string
+
+	if v, ok := d.GetOk("watch_recipients"); ok {
+		recipients := v.(*schema.Set).List()
+		for _, watchRec := range recipients {
+			watchRecipients = append(watchRecipients, watchRec.(string))
+		}
+	}
+	watch.WatchRecipients = watchRecipients
+
+	return watch
+}
+
+func unpackProjectResource(rawCfg interface{}) WatchProjectResource {
+	resource := WatchProjectResource{}
+
+	cfg := rawCfg.(map[string]interface{})
+	resource.Type = cfg["type"].(string)
+
+	if v, ok := cfg["bin_mgr_id"]; ok {
+		resource.BinaryManagerId = v.(string)
+	}
+	if v, ok := cfg["name"]; ok {
+		resource.Name = v.(string)
+	}
+
+	if v, ok := cfg["filter"]; ok {
+		resourceFilters := unpackFilters(v.([]interface{}))
+		resource.Filters = resourceFilters
+	}
+
+	return resource
+}
+
+func unpackFilters(list []interface{}) []WatchFilter {
+	var filters []WatchFilter
+
+	for _, raw := range list {
+		filter := WatchFilter{}
+		f := raw.(map[string]interface{})
+		filter.Type = f["type"].(string)
+		filter.Value = f["value"].(string)
+		filters = append(filters, filter)
+	}
+
+	return filters
+}
+
+func unpackAssignedPolicy(rawCfg interface{}) WatchAssignedPolicy {
+	policy := WatchAssignedPolicy{}
+
+	cfg := rawCfg.(map[string]interface{})
+	policy.Name = cfg["name"].(string)
+	policy.Type = cfg["type"].(string)
+
+	return policy
+}
+
+func packProjectResources(resources WatchProjectResources) []interface{} {
+	var list []interface{}
+	for _, res := range resources.Resources {
+		resourceMap := map[string]interface{}{}
+		resourceMap["type"] = res.Type
+		if len(res.Name) > 0 {
+			resourceMap["name"] = res.Name
+		}
+		if len(res.BinaryManagerId) > 0 {
+			resourceMap["bin_mgr_id"] = res.BinaryManagerId
+		}
+		resourceMap["filter"] = packFilters(res.Filters)
+		list = append(list, resourceMap)
+	}
+
+	return list
+}
+
+func packFilters(filters []WatchFilter) []interface{} {
+	var l []interface{}
+	for _, f := range filters {
+		m := map[string]interface{}{
+			"type":  f.Type,
+			"value": f.Value,
+		}
+		l = append(l, m)
+	}
+
+	return l
+}
+
+func packAssignedPolicies(policies []WatchAssignedPolicy) []interface{} {
+	var l []interface{}
+	for _, p := range policies {
+		m := make(map[string]interface{})
+		m["name"] = p.Name
+		m["type"] = p.Type
+		l = append(l, m)
+	}
+
+	return l
+}
+
+func resourceXrayWatchCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+	watch := unpackWatch(d)
+	_, err := m.(*resty.Client).R().SetBody(watch).Post("xray/api/v2/watches")
+	if err != nil {
+		return diag.FromErr(err)
+	}
+
+	d.SetId(watch.GeneralData.Name)
+	return resourceXrayWatchRead(ctx, d, m)
+}
+
+func resourceXrayWatchRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+	watch := Watch{}
+	resp, err := m.(*resty.Client).R().SetResult(&watch).Get("xray/api/v2/watches/" + d.Id())
+	if err != nil {
+		if resp != nil && resp.StatusCode() == http.StatusNotFound {
+			log.Printf("[WARN] Xray watch (%s) not found, removing from state", d.Id())
+			d.SetId("")
+		}
+		return diag.FromErr(err)
+	}
+	if err := d.Set("description", watch.GeneralData.Description); err != nil {
+		return diag.FromErr(err)
+	}
+	if err := d.Set("active", watch.GeneralData.Active); err != nil {
+		return diag.FromErr(err)
+	}
+	if err := d.Set("watch_resource", packProjectResources(watch.ProjectResources)); err != nil {
+		return diag.FromErr(err)
+	}
+	if err := d.Set("assigned_policy", packAssignedPolicies(watch.AssignedPolicies)); err != nil {
+		return diag.FromErr(err)
+	}
+
+	return nil
+}
+
+func resourceXrayWatchUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+	watch := unpackWatch(d)
+	resp, err := m.(*resty.Client).R().SetBody(watch).Put("xray/api/v2/watches/" + d.Id())
+	if err != nil {
+		if resp != nil && resp.StatusCode() == http.StatusNotFound {
+			log.Printf("[WARN] Xray watch (%s) not found, removing from state", d.Id())
+			d.SetId("")
+		}
+		return diag.FromErr(err)
+	}
+
+	d.SetId(watch.GeneralData.Name)
+	return resourceXrayWatchRead(ctx, d, m)
+}
+
+func resourceXrayWatchDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+	resp, err := m.(*resty.Client).R().Delete("xray/api/v2/watches/" + d.Id())
+	if err != nil && resp.StatusCode() == http.StatusNotFound {
+		d.SetId("")
+		return diag.FromErr(err)
+	}
+	return nil
+}
diff --git a/sample.tf b/sample.tf
index cee2790d..1e60ba5d 100644
--- a/sample.tf
+++ b/sample.tf
@@ -9,7 +9,11 @@ terraform {
 }
 
 provider "xray" {
-  //  supply ARTIFACTORY_URL (or JFROG_URL) and ARTIFACTORY_ACCESS_TOKEN (or XRAY_ACCESS_TOKEN/JFROG_ACCESS_TOKEN) as env vars
+  url          = "artifactory.site.com/xray"
+  access_token = "abc..xy"
+  // Also user can supply the following env vars:
+  // JFROG_URL or XRAY_URL
+  // XRAY_ACCESS_TOKEN or JFROG_ACCESS_TOKEN
 }
 
 resource "random_id" "randid" {
@@ -20,25 +24,29 @@ resource "xray_security_policy" "security1" {
   name        = "test-security-policy-severity-${random_id.randid.dec}"
   description = "Security policy description"
   type        = "security"
-  rules {
+
+  rule {
     name     = "rule-name-severity"
     priority = 1
+
     criteria {
       min_severity = "High"
     }
+
     actions {
       webhooks = []
       mails    = ["test@email.com"]
-      block_download {
-        unscanned = true
-        active    = true
-      }
       block_release_bundle_distribution  = true
       fail_build                         = true
       notify_watch_recipients            = true
       notify_deployer                    = true
-      create_ticket_enabled              = false  // set to true only if Jira integration is enabled
-      build_failure_grace_period_in_days = 5      // use only if fail_build is enabled
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      build_failure_grace_period_in_days = 5     // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
     }
   }
 }
@@ -47,28 +55,33 @@ resource "xray_security_policy" "security2" {
   name        = "test-security-policy-cvss-${random_id.randid.dec}"
   description = "Security policy description"
   type        = "security"
-  rules {
+
+  rule {
     name     = "rule-name-cvss"
     priority = 1
+
     criteria {
+
       cvss_range {
         from = 1.5
         to   = 5.3
       }
     }
+
     actions {
       webhooks = []
       mails    = ["test@email.com"]
-      block_download {
-        unscanned = true
-        active    = true
-      }
       block_release_bundle_distribution  = true
       fail_build                         = true
       notify_watch_recipients            = true
       notify_deployer                    = true
-      create_ticket_enabled              = false  // set to true only if Jira integration is enabled
-      build_failure_grace_period_in_days = 5      // use only if fail_build is enabled
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
+      build_failure_grace_period_in_days = 5     // use only if fail_build is enabled
+
+      block_download {
+        unscanned = true
+        active    = true
+      }
     }
   }
 }
@@ -77,29 +90,32 @@ resource "xray_license_policy" "license1" {
   name        = "test-license-policy-allowed-${random_id.randid.dec}"
   description = "License policy, allow certain licenses"
   type        = "license"
-  rules {
+
+  rule {
     name     = "License_rule"
     priority = 1
+
     criteria {
       allowed_licenses         = ["Apache-1.0", "Apache-2.0"]
       allow_unknown            = false
       multi_license_permissive = true
     }
+
     actions {
       webhooks = []
       mails    = ["test@email.com"]
-      block_download {
-        unscanned = true
-        active    = true
-      }
       block_release_bundle_distribution  = false
       fail_build                         = true
       notify_watch_recipients            = true
       notify_deployer                    = true
-      create_ticket_enabled              = false      // set to true only if Jira integration is enabled
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
       custom_severity                    = "High"
-      build_failure_grace_period_in_days = 5          // use only if fail_build is enabled
+      build_failure_grace_period_in_days = 5 // use only if fail_build is enabled
 
+      block_download {
+        unscanned = true
+        active    = true
+      }
     }
   }
 }
@@ -108,29 +124,127 @@ resource "xray_license_policy" "license2" {
   name        = "test-license-policy-banned-${random_id.randid.dec}"
   description = "License policy, block certain licenses"
   type        = "license"
-  rules {
+
+  rule {
     name     = "License_rule"
     priority = 1
+
     criteria {
-      banned_licenses          = ["Apache-3.0", "Apache-4.0"]
+      banned_licenses          = ["Apache-1.1", "APAFML"]
       allow_unknown            = false
       multi_license_permissive = false
     }
+
     actions {
       webhooks = []
       mails    = ["test@email.com"]
-      block_download {
-        unscanned = true
-        active    = true
-      }
       block_release_bundle_distribution  = false
       fail_build                         = true
       notify_watch_recipients            = true
       notify_deployer                    = true
-      create_ticket_enabled              = false      // set to true only if Jira integration is enabled
+      create_ticket_enabled              = false // set to true only if Jira integration is enabled
       custom_severity                    = "Medium"
-      build_failure_grace_period_in_days = 5          // use only if fail_build is enabled
+      build_failure_grace_period_in_days = 5 // use only if fail_build is enabled
 
+      block_download {
+        unscanned = true
+        active    = true
+      }
     }
   }
+}
+
+resource "xray_watch" "all-repos" {
+  name        = "all-repos-watch-${random_id.randid.dec}"
+  description = "Watch for all repositories, matching the filter"
+  active      = true
+
+  watch_resource {
+    type = "all-repos"
+
+    filter {
+      type  = "regex"
+      value = ".*"
+    }
+  }
+
+  assigned_policy {
+    name = xray_security_policy.security1.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.license1.name
+    type = "license"
+  }
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
+
+resource "xray_watch" "repository" {
+  name        = "repository-watch-${random_id.randid.dec}"
+  description = "Watch a single repo or a list of repositories"
+  active      = true
+
+  watch_resource {
+    type       = "repository"
+    bin_mgr_id = "default"
+    name       = "your-repository-name"
+
+    filter {
+      type  = "regex"
+      value = ".*"
+    }
+  }
+
+  watch_resource {
+    type       = "repository"
+    bin_mgr_id = "default"
+    name       = "your-other-repository-name"
+
+    filter {
+      type  = "package-type"
+      value = "Docker"
+    }
+  }
+
+  assigned_policy {
+    name = xray_security_policy.security1.name
+    type = "security"
+  }
+
+  assigned_policy {
+    name = xray_license_policy.license1.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
+}
+
+resource "xray_watch" "build" {
+  name        = "build-watch-${random_id.randid.dec}"
+  description = "Watch a single build or a list of builds"
+  active      = true
+
+  watch_resource {
+    type       = "build"
+    bin_mgr_id = "default"
+    name       = "your-build-name"
+  }
+
+  watch_resource {
+    type       = "build"
+    bin_mgr_id = "default"
+    name       = "your-other-build-name"
+  }
+
+  assigned_policy {
+    name = xray_security_policy.security1.name
+    type = "security"
+  }
+  assigned_policy {
+    name = xray_license_policy.license1.name
+    type = "license"
+  }
+
+  watch_recipients = ["test@email.com", "test1@email.com"]
 }
\ No newline at end of file
diff --git a/templates/debug.md b/templates/debug.md
new file mode 100644
index 00000000..bed2e22f
--- /dev/null
+++ b/templates/debug.md
@@ -0,0 +1,51 @@
+#  Debugging a TerraForm provider
+
+## Understanding the design
+
+In order to do it, you first have to understand how Go builds apps, and then how terraform works with it.
+
+Every terraform provider is a sort of `module`. In order to support an open, modular system, in almost any language, you need to be able to dynamically load modules and interact with them. Terraform is no exception.
+
+However, the go lang team long ago decided to compile to statically linked applications;
+any dependencies you have will be compiled into 1 single binary. Unlike in other native languages (like C, or C++), a
+`.dll` or `.so` is not used; there is no dynamic library to load at runtime and thus, modularity becomes a whole other trick.
+This is done to avoid the notorious **dll hell** that was so common up until most modern systems included some
+kind of dependency management. And yes, it can still be an issue.
+
+Every terraform provider is its own mini RPC server. When terraform runs your provider, it actually starts a new process that is your provider, and connects to it through
+this RPC channel. Compounding the problem is that the lifetime of your provider process is very much
+ephemeral; potentially lasting no more and a few seconds. It's this process you need to connect to with your debugger
+
+### Normal debugging
+Normally, you would directly spin-up your app, and it would load modules into application memory. That's why you can actually
+debug it, because your debugger knows how to find the exact memory address for your provider. However, you don't have
+this arrangement, and you need to do a _remote_ debug session.
+
+### The conundrum
+So, you don't load terraform directly, and even if you did, your `module` (a.k.a your provider) is in the memory
+space of an entirely different process; and that lasts no more than a few seconds, potentially.
+
+## The solution
+
+1. You need the debugging tool [delve](https://github.com/go-delve/delve).
+2. You are going to have to place a little bit of shim code close to the spot in the code where you want to begin
+   debugging. We need to stop this provider process from exiting before we can connect. So, put this bit of code in place:
+```go
+	connected := false
+for !connected {
+time.Sleep(time.Second) // set breakpoint here
+}
+```
+This code effectively creates an infinite sleep loop; but that's actually essential to solving the problem.
+
+3. Place a break point right inside this loop. It won't do anything, yet.
+4. Now run the terraform commands you need to, to engage the code you're desiring to debug. Upon doing so,
+   terraform will basically stop, as it waits on a response from you provider; because you put an infinite sleep loop in
+5. You must now tell `delve` to connect to this remote process using it's PID. This isn't as hard as it seems.
+   Run this commands:
+   `dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient attach $(pgrep terraform-provider-xray)`
+   The last argument gets the `PID` for your provider and supplies it to `delve` to connect. Immediately upon running this
+   command, you're going to hit your break point. Please make sure to substitute `terraform-provider-xray` for your provider name
+6. To exit this infinite loop, use your debugger to set `connected` to `true`. By doing so you change the loop predicate
+   and it will exit this loop on the next iteration.
+7. *DEBUG!* - At this point you can, step, watch, drop the call stack, etc. Your whole arsenel is available
diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl
new file mode 100644
index 00000000..bb381d9b
--- /dev/null
+++ b/templates/index.md.tmpl
@@ -0,0 +1,60 @@
+---
+layout: ""
+page_title: "JFrog Xray Provider"
+description: |-
+  The Xray provider is used to interact with the resources supported by JFrog Xray.
+---
+
+# JFrog Xray Provider
+
+The [Xray](https://jfrog.com/xray/) provider is used to interact with the
+resources supported by JFrog Xray. Xray is a part of JFrog Artifactory and can't be used separately.
+The provider needs to be configured with the proper credentials before it can be used.
+Xray API documentation can be found [here](https://www.jfrog.com/confluence/display/JFROG/Xray+REST+API)
+
+Links to documentation for specific resources can be found in the table of contents to the left.
+
+This provider requires access to Artifactory and Xray APIs, which are only available in the _licensed_ pro and enterprise editions.
+You can determine which license you have by accessing the following URL
+`${host}/artifactory/api/system/licenses/`
+
+You can either access it via api, or web browser - it does require admin level credentials, but it's one of the few APIs that will work without a license (side node: you can also install your license here with a `POST`)
+
+```bash
+curl -sL ${host}/projects/api/system/licenses/ | jq .
+{
+  "type" : "Enterprise Plus Trial",
+  "validThrough" : "Jan 29, 2022",
+  "licensedTo" : "JFrog Ltd"
+}
+```
+
+The following 3 license types (`jq .type`) do **NOT** support APIs:
+- Community Edition for C/C++
+- JCR Edition
+- OSS
+
+## Example Usage
+
+{{tffile "examples/sample.tf"}}
+
+## Authentication
+
+The Xray provider supports one type of authentication using Bearer token.
+
+### Bearer Token
+Artifactory access tokens may be used via the Authorization header by providing the `access_token` field to the provider
+block. Getting this value from the environment is supported with the `XRAY_ACCESS_TOKEN`,
+or `JFROG_ACCESS_TOKEN` variables.
+Set `url` field to provide JFrog Xray URL. Alternatively you can set `ARTIFACTORY_URL`, `JFROG_URL` or `PROJECTS_URL` variables.
+
+Usage:
+```hcl
+# Configure the Xray provider
+provider "xray" {
+  url = "artifactory.site.com/xray"
+  access_token = "abc...xy"
+}
+```
+
+{{ .SchemaMarkdown | trimspace }}


Test patch:
diff --git a/pkg/xray/provider_test.go b/pkg/xray/provider_test.go
index bf549381..3e8f8591 100644
--- a/pkg/xray/provider_test.go
+++ b/pkg/xray/provider_test.go
@@ -2,22 +2,25 @@ package xray
 
 import (
 	"context"
-	"github.com/go-resty/resty/v2"
+	"fmt"
+	"net/http"
 	"os"
+	"strings"
 	"testing"
 
+	"github.com/go-resty/resty/v2"
+
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
 	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
 )
 
-var testAccProviders = func() map[string]func() (*schema.Provider, error) {
-	provider := Provider()
+func testAccProviders() map[string]func() (*schema.Provider, error) {
 	return map[string]func() (*schema.Provider, error){
 		"xray": func() (*schema.Provider, error) {
-			return provider, nil
+			return Provider(), nil
 		},
 	}
-}()
+}
 
 func TestProvider(t *testing.T) {
 	if err := Provider().InternalValidate(); err != nil {
@@ -26,32 +29,95 @@ func TestProvider(t *testing.T) {
 }
 
 func getTestResty(t *testing.T) *resty.Client {
-	if v := os.Getenv("ARTIFACTORY_URL"); v == "" {
-		t.Fatal("ARTIFACTORY_URL must be set for acceptance tests")
+	if v := os.Getenv("JFROG_URL"); v == "" {
+		t.Error("JFROG_URL must be set for acceptance tests")
 	}
-	restyClient, err := buildResty(os.Getenv("ARTIFACTORY_URL"))
+	restyClient, err := buildResty(os.Getenv("JFROG_URL"))
 	if err != nil {
-		t.Fatal(err)
+		t.Error(err)
 	}
-	accessToken := os.Getenv("ARTIFACTORY_ACCESS_TOKEN")
+	accessToken := os.Getenv("XRAY_ACCESS_TOKEN")
 	restyClient, err = addAuthToResty(restyClient, accessToken)
 	if err != nil {
-		t.Fatal(err)
+		t.Error(err)
 	}
 	return restyClient
 }
 
 func testAccPreCheck(t *testing.T) {
-	restyClient := getTestResty(t)
-	// TODO check the payload and make sure it's the right license type
-	_, err := restyClient.R().Get("/artifactory/api/system/licenses/")
-	if err != nil {
-		t.Fatal(err)
-	}
 	ctx := context.Background()
-	provider, _ := testAccProviders["xray"]()
+	provider, _ := testAccProviders()["xray"]()
 	oldErr := provider.Configure(ctx, terraform.NewResourceConfigRaw(nil))
 	if oldErr != nil {
-		t.Fatal(oldErr)
+		t.Error(oldErr)
 	}
 }
+
+// Create a local repository with Xray indexing enabled. It will be used in the tests
+func testAccCreateRepos(t *testing.T, repo string) {
+	restyClient := getTestResty(t)
+
+	type Repository struct {
+		Rclass    string `json:"rclass"`
+		XrayIndex bool   `json:"xrayIndex"`
+	}
+
+	repository := Repository{}
+	repository.Rclass = "local"
+	repository.XrayIndex = true
+	response, errRepo := restyClient.R().SetBody(repository).Put("artifactory/api/repositories/" + repo)
+	//Artifactory can return 400 for several reasons, this is why we are checking the response body
+	repoExists := strings.Contains(fmt.Sprint(errRepo), "Case insensitive repository key already exists")
+	if !repoExists && response.StatusCode() != http.StatusOK {
+		t.Error(errRepo)
+	}
+}
+
+func testAccDeleteRepo(t *testing.T, repo string) {
+	restyClient := getTestResty(t)
+
+	response, errRepo := restyClient.R().Delete("artifactory/api/repositories/" + repo)
+	if errRepo != nil || response.StatusCode() != http.StatusOK {
+		t.Logf("The repository %s wasn't removed", repo)
+	}
+}
+
+// Create a set of builds or a single build, add the build into the Xray indexing configuration, to be able to add it to
+// the xray watch
+func testAccCreateBuilds(t *testing.T, builds []string) {
+	restyClient := getTestResty(t)
+
+	type BuildBody struct {
+		Version string `json:"version"`
+		Name    string `json:"name"`
+		Number  string `json:"number"`
+		Started string `json:"started"`
+	}
+
+	type XrayIndexBody struct {
+		Names []string `json:"names"`
+	}
+
+	for _, build := range builds {
+		buildBody := BuildBody{
+			Version: "1.0.1",
+			Name:    build,
+			Number:  "28",
+			Started: "2021-10-30T12:00:19.893+0300",
+		}
+		respCreateBuild, errCreateBuild := restyClient.R().SetBody(buildBody).Put("artifactory/api/build")
+		if respCreateBuild.StatusCode() != http.StatusNoContent {
+			t.Error(errCreateBuild)
+		}
+	}
+
+	xrayIndexBody := XrayIndexBody{
+		Names: builds,
+	}
+
+	respAddIndexBody, errAddIndexBody := restyClient.R().SetBody(xrayIndexBody).Post("xray/api/v1/binMgr/builds")
+	if respAddIndexBody.StatusCode() != http.StatusOK {
+		t.Error(errAddIndexBody)
+	}
+
+}
diff --git a/pkg/xray/resource_xray_license_policy_test.go b/pkg/xray/resource_xray_license_policy_test.go
index 248c89fb..8910f405 100644
--- a/pkg/xray/resource_xray_license_policy_test.go
+++ b/pkg/xray/resource_xray_license_policy_test.go
@@ -2,14 +2,10 @@ package xray
 
 import (
 	"fmt"
-	"net/http"
 	"regexp"
 	"testing"
 
-	"github.com/go-resty/resty/v2"
-
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
-	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
 )
 
 var tempStructLicense = map[string]string{
@@ -37,19 +33,19 @@ var tempStructLicense = map[string]string{
 
 // License policy criteria are different from the security policy criteria
 // Test will try to post a new license policy with incorrect body of security policy
-// with specified cvss_range. The function expandLicenseCriteria will ignore all the
+// with specified cvss_range. The function unpackLicenseCriteria will ignore all the
 // fields except of "allow_unknown", "banned_licenses" and "allowed_licenses" if the Policy type is "license"
 func TestAccLicensePolicy_badLicenseCriteria(t *testing.T) {
 	_, fqrn, resourceName := mkNames("policy-", "xray_license_policy")
-	policyName := "terraform-license-policy-1"
+	policyName := fmt.Sprintf("terraform-license-policy-1-%d", randomInt())
 	policyDesc := "policy created by xray acceptance tests"
-	ruleName := "test-license-rule-1"
+	ruleName := fmt.Sprintf("test-license-rule-1-%d", randomInt())
 	rangeTo := 5
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckLicensePolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config:      testAccXrayLicensePolicy_badLicense(resourceName, policyName, policyDesc, ruleName, rangeTo),
@@ -66,15 +62,15 @@ func TestAccLicensePolicy_badGracePeriod(t *testing.T) {
 	copyStringMap(tempStructLicense, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-security-policy-2"
-	tempStruct["rule_name"] = "test-license-rule-2"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-security-policy-2-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-license-rule-2-%d", randomInt())
 	tempStruct["fail_build"] = "false"
 	tempStruct["grace_period_days"] = "5"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckLicensePolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config:      executeTemplate(fqrn, licensePolicyTemplate, tempStruct),
@@ -90,15 +86,15 @@ func TestAccLicensePolicy_createAllowedLic(t *testing.T) {
 	copyStringMap(tempStructLicense, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-license-policy-3"
-	tempStruct["rule_name"] = "test-license-rule-3"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-license-policy-3-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-license-rule-3-%d", randomInt())
 	tempStruct["multi_license_permissive"] = "true"
 	tempStruct["allowedOrBanned"] = "allowed_licenses"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckLicensePolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, licensePolicyTemplate, tempStruct),
@@ -114,14 +110,14 @@ func TestAccLicensePolicy_createBannedLic(t *testing.T) {
 	copyStringMap(tempStructLicense, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-license-policy-4"
-	tempStruct["rule_name"] = "test-license-rule-4"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-license-policy-4-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-license-rule-4-%d", randomInt())
 	tempStruct["allowedOrBanned"] = "banned_licenses"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckLicensePolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, licensePolicyTemplate, tempStruct),
@@ -137,14 +133,14 @@ func TestAccLicensePolicy_createMultiLicensePermissiveFalse(t *testing.T) {
 	copyStringMap(tempStructLicense, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-license-policy-5"
-	tempStruct["rule_name"] = "test-license-rule-5"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-license-policy-5-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-license-rule-5-%d", randomInt())
 	tempStruct["allowedOrBanned"] = "banned_licenses"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckLicensePolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, licensePolicyTemplate, tempStruct),
@@ -160,16 +156,16 @@ func TestAccLicensePolicy_createBlockFalse(t *testing.T) {
 	copyStringMap(tempStructLicense, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-license-policy-6"
-	tempStruct["rule_name"] = "test-license-rule-6"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-license-policy-6-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-license-rule-6-%d", randomInt())
 	tempStruct["block_unscanned"] = "true"
 	tempStruct["block_active"] = "true"
 	tempStruct["allowedOrBanned"] = "banned_licenses"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckLicensePolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, licensePolicyTemplate, tempStruct),
@@ -179,29 +175,13 @@ func TestAccLicensePolicy_createBlockFalse(t *testing.T) {
 	})
 }
 
-func testAccCheckLicensePolicyDestroy(id string) func(*terraform.State) error {
-	return func(s *terraform.State) error {
-		rs, ok := s.RootModule().Resources[id]
-		if !ok {
-			return fmt.Errorf("error: Resource id [%s] not found", id)
-		}
-		provider, _ := testAccProviders["xray"]()
-		_, resp, _ := getPolicy(rs.Primary.ID, provider.Meta().(*resty.Client))
-
-		if resp.StatusCode() == http.StatusOK {
-			return fmt.Errorf("error: Policy %s still exists", rs.Primary.ID)
-		}
-		return nil
-	}
-}
-
 func testAccXrayLicensePolicy_badLicense(resourceName, name, description, ruleName string, rangeTo int) string {
 	return fmt.Sprintf(`
 resource "xray_security_policy" "%s" {
 	name = "%s"
 	description = "%s"
 	type = "license"
-	rules {
+	rule {
 		name = "%s"
 		priority = 1
 		criteria {
@@ -225,22 +205,22 @@ func verifyLicensePolicy(fqrn string, tempStruct map[string]string, allowedOrBan
 	return resource.ComposeTestCheckFunc(
 		resource.TestCheckResourceAttr(fqrn, "name", tempStruct["policy_name"]),
 		resource.TestCheckResourceAttr(fqrn, "description", tempStruct["policy_description"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.name", tempStruct["rule_name"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.criteria.0.allow_unknown", tempStruct["allow_unknown"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.criteria.0.multi_license_permissive", tempStruct["multi_license_permissive"]),
-		resource.TestCheckResourceAttr(fqrn, fmt.Sprintf("rules.0.criteria.0.%s.0", allowedOrBanned), tempStruct["license_0"]),
-		resource.TestCheckResourceAttr(fqrn, fmt.Sprintf("rules.0.criteria.0.%s.1", allowedOrBanned), tempStruct["license_1"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.mails.0", tempStruct["mails_0"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.mails.1", tempStruct["mails_1"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.block_release_bundle_distribution", tempStruct["block_release_bundle_distribution"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.fail_build", tempStruct["fail_build"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.notify_watch_recipients", tempStruct["notify_watch_recipients"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.notify_deployer", tempStruct["notify_deployer"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.create_ticket_enabled", tempStruct["create_ticket_enabled"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.build_failure_grace_period_in_days", tempStruct["grace_period_days"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.block_download.0.active", tempStruct["block_active"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.block_download.0.unscanned", tempStruct["block_unscanned"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.custom_severity", tempStruct["custom_severity"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.name", tempStruct["rule_name"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.criteria.0.allow_unknown", tempStruct["allow_unknown"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.criteria.0.multi_license_permissive", tempStruct["multi_license_permissive"]),
+		resource.TestCheckResourceAttr(fqrn, fmt.Sprintf("rule.0.criteria.0.%s.0", allowedOrBanned), tempStruct["license_0"]),
+		resource.TestCheckResourceAttr(fqrn, fmt.Sprintf("rule.0.criteria.0.%s.1", allowedOrBanned), tempStruct["license_1"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.mails.0", tempStruct["mails_0"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.mails.1", tempStruct["mails_1"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.block_release_bundle_distribution", tempStruct["block_release_bundle_distribution"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.fail_build", tempStruct["fail_build"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.notify_watch_recipients", tempStruct["notify_watch_recipients"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.notify_deployer", tempStruct["notify_deployer"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.create_ticket_enabled", tempStruct["create_ticket_enabled"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.build_failure_grace_period_in_days", tempStruct["grace_period_days"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.block_download.0.active", tempStruct["block_active"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.block_download.0.unscanned", tempStruct["block_unscanned"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.custom_severity", tempStruct["custom_severity"]),
 	)
 }
 
@@ -248,7 +228,7 @@ const licensePolicyTemplate = `resource "xray_license_policy" "{{ .resource_name
 	name = "{{ .policy_name }}"
 	description = "{{ .policy_description }}"
 	type = "license"
-	rules {
+	rule {
 		name = "{{ .rule_name }}"
 		priority = 1
 		criteria {	
diff --git a/pkg/xray/resource_xray_security_policy_test.go b/pkg/xray/resource_xray_security_policy_test.go
index 0d780d10..9bc91399 100644
--- a/pkg/xray/resource_xray_security_policy_test.go
+++ b/pkg/xray/resource_xray_security_policy_test.go
@@ -2,15 +2,11 @@ package xray
 
 import (
 	"fmt"
-	"net/http"
 	"regexp"
 	"strconv"
 	"testing"
 
-	"github.com/go-resty/resty/v2"
-
 	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
-	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
 )
 
 var tempStructSecurity = map[string]string{
@@ -35,16 +31,16 @@ var tempStructSecurity = map[string]string{
 // Teh test will try to create a security policy with the type of "license"
 // The Policy criteria will be ignored in this case
 func TestAccSecurityPolicy_badTypeInSecurityPolicy(t *testing.T) {
-	policyName := "terraform-security-policy-1"
+	policyName := fmt.Sprintf("terraform-security-policy-1-%d", randomInt())
 	policyDesc := "policy created by xray acceptance tests"
-	ruleName := "test-security-rule-1"
+	ruleName := fmt.Sprintf("test-security-rule-1-%d", randomInt())
 	rangeTo := 5
 	resourceName := "policy-" + strconv.Itoa(randomInt())
 	fqrn := "xray_security_policy." + resourceName
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config:      testAccXraySecurityPolicy_badSecurityType(policyName, policyDesc, ruleName, rangeTo),
@@ -57,16 +53,16 @@ func TestAccSecurityPolicy_badTypeInSecurityPolicy(t *testing.T) {
 // The test will try to use "allowed_licenses" in the security policy criteria
 // That field is acceptable only in license policy. No API call, expected to fail on the TF resource verification
 func TestAccSecurityPolicy_badSecurityCriteria(t *testing.T) {
-	policyName := "terraform-security-policy-2"
+	policyName := fmt.Sprintf("terraform-security-policy-2-%d", randomInt())
 	policyDesc := "policy created by xray acceptance tests"
-	ruleName := "test-security-rule-2"
+	ruleName := fmt.Sprintf("test-security-rule-2-%d", randomInt())
 	allowedLicense := "BSD-4-Clause"
 	resourceName := "policy-" + strconv.Itoa(randomInt())
 	fqrn := "xray_security_policy." + resourceName
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config:      testAccXraySecurityPolicy_badSecurity(policyName, policyDesc, ruleName, allowedLicense),
@@ -84,15 +80,15 @@ func TestAccSecurityPolicy_badGracePeriod(t *testing.T) {
 	copyStringMap(tempStructSecurity, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-security-policy-3"
-	tempStruct["rule_name"] = "test-security-rule-3"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-security-policy-3-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-security-rule-3-%d", randomInt())
 	tempStruct["fail_build"] = "false"
 	tempStruct["grace_period_days"] = "5"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config:      executeTemplate(fqrn, securityPolicyCVSS, tempStruct),
@@ -109,14 +105,14 @@ func TestAccSecurityPolicy_createBlockDownloadTrueCVSS(t *testing.T) {
 	copyStringMap(tempStructSecurity, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-security-policy-4"
-	tempStruct["rule_name"] = "test-security-rule-4"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-security-policy-4-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-security-rule-4-%d", randomInt())
 	tempStruct["cvssOrSeverity"] = "cvss"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, securityPolicyCVSS, tempStruct),
@@ -133,16 +129,16 @@ func TestAccSecurityPolicy_createBlockDownloadFalseCVSS(t *testing.T) {
 	copyStringMap(tempStructSecurity, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-security-policy-5"
-	tempStruct["rule_name"] = "test-security-rule-5"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-security-policy-5-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-security-rule-5-%d", randomInt())
 	tempStruct["block_unscanned"] = "false"
 	tempStruct["block_active"] = "false"
 	tempStruct["cvssOrSeverity"] = "cvss"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, securityPolicyCVSS, tempStruct),
@@ -159,14 +155,14 @@ func TestAccSecurityPolicy_createBlockDownloadTrueMinSeverity(t *testing.T) {
 	copyStringMap(tempStructSecurity, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-security-policy-6"
-	tempStruct["rule_name"] = "test-security-rule-6"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-security-policy-6-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-security-rule-6-%d", randomInt())
 	tempStruct["cvssOrSeverity"] = "severity"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, securityPolicyMinSeverity, tempStruct),
@@ -183,16 +179,16 @@ func TestAccSecurityPolicy_createBlockDownloadFalseMinSeverity(t *testing.T) {
 	copyStringMap(tempStructSecurity, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-security-policy-7"
-	tempStruct["rule_name"] = "test-security-rule-7"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-security-policy-7-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-security-rule-7-%d", randomInt())
 	tempStruct["block_unscanned"] = "false"
 	tempStruct["block_active"] = "false"
 	tempStruct["cvssOrSeverity"] = "severity"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, securityPolicyMinSeverity, tempStruct),
@@ -209,16 +205,16 @@ func TestAccSecurityPolicy_createCVSSFloat(t *testing.T) {
 	copyStringMap(tempStructSecurity, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-security-policy-8"
-	tempStruct["rule_name"] = "test-security-rule-8"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-security-policy-8-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-security-rule-8-%d", randomInt())
 	tempStruct["cvss_from"] = "1.5"
 	tempStruct["cvss_to"] = "5.3"
 	tempStruct["cvssOrSeverity"] = "cvss"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, securityPolicyCVSS, tempStruct),
@@ -234,15 +230,15 @@ func TestAccSecurityPolicy_blockMismatchCVSS(t *testing.T) {
 	copyStringMap(tempStructSecurity, tempStruct)
 
 	tempStruct["resource_name"] = resourceName
-	tempStruct["policy_name"] = "terraform-security-policy-9"
-	tempStruct["rule_name"] = "test-security-rule-9"
+	tempStruct["policy_name"] = fmt.Sprintf("terraform-security-policy-9-%d", randomInt())
+	tempStruct["rule_name"] = fmt.Sprintf("test-security-rule-9-%d", randomInt())
 	tempStruct["block_unscanned"] = "true"
 	tempStruct["block_active"] = "false"
 
 	resource.Test(t, resource.TestCase{
 		PreCheck:          func() { testAccPreCheck(t) },
-		CheckDestroy:      testAccCheckSecurityPolicyDestroy(fqrn),
-		ProviderFactories: testAccProviders,
+		CheckDestroy:      verifyDeleted(fqrn, testCheckPolicy),
+		ProviderFactories: testAccProviders(),
 		Steps: []resource.TestStep{
 			{
 				Config: executeTemplate(fqrn, securityPolicyCVSS, tempStruct),
@@ -253,29 +249,13 @@ func TestAccSecurityPolicy_blockMismatchCVSS(t *testing.T) {
 	})
 }
 
-func testAccCheckSecurityPolicyDestroy(id string) func(*terraform.State) error {
-	return func(s *terraform.State) error {
-		rs, ok := s.RootModule().Resources[id]
-		if !ok {
-			return fmt.Errorf("error: Resource id [%s] not found", id)
-		}
-		provider, _ := testAccProviders["xray"]()
-		_, resp, _ := getPolicy(rs.Primary.ID, provider.Meta().(*resty.Client))
-
-		if resp.StatusCode() == http.StatusOK {
-			return fmt.Errorf("error: Policy %s still exists", rs.Primary.ID)
-		}
-		return nil
-	}
-}
-
 func testAccXraySecurityPolicy_badSecurityType(name, description, ruleName string, rangeTo int) string {
 	return fmt.Sprintf(`
 resource "xray_security_policy" "test" {
 	name = "%s"
 	description = "%s"
 	type = "license"
-	rules {
+	rule {
 		name = "%s"
 		priority = 1
 		criteria {
@@ -301,7 +281,7 @@ resource "xray_security_policy" "test" {
 	name = "%s"
 	description = "%s"
 	type = "security"
-	rules {
+	rule {
 		name = "%s"
 		priority = 1
 		criteria {
@@ -323,27 +303,27 @@ func verifySecurityPolicy(fqrn string, tempStruct map[string]string, cvssOrSever
 	var commonCheckList = resource.ComposeTestCheckFunc(
 		resource.TestCheckResourceAttr(fqrn, "name", tempStruct["policy_name"]),
 		resource.TestCheckResourceAttr(fqrn, "description", tempStruct["policy_description"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.name", tempStruct["rule_name"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.block_release_bundle_distribution", tempStruct["block_release_bundle_distribution"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.fail_build", tempStruct["fail_build"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.notify_watch_recipients", tempStruct["notify_watch_recipients"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.notify_deployer", tempStruct["notify_deployer"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.create_ticket_enabled", tempStruct["create_ticket_enabled"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.build_failure_grace_period_in_days", tempStruct["grace_period_days"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.block_download.0.active", tempStruct["block_active"]),
-		resource.TestCheckResourceAttr(fqrn, "rules.0.actions.0.block_download.0.unscanned", tempStruct["block_unscanned"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.name", tempStruct["rule_name"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.block_release_bundle_distribution", tempStruct["block_release_bundle_distribution"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.fail_build", tempStruct["fail_build"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.notify_watch_recipients", tempStruct["notify_watch_recipients"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.notify_deployer", tempStruct["notify_deployer"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.create_ticket_enabled", tempStruct["create_ticket_enabled"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.build_failure_grace_period_in_days", tempStruct["grace_period_days"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.block_download.0.active", tempStruct["block_active"]),
+		resource.TestCheckResourceAttr(fqrn, "rule.0.actions.0.block_download.0.unscanned", tempStruct["block_unscanned"]),
 	)
 	if cvssOrSeverity == "cvss" {
 		return resource.ComposeTestCheckFunc(
 			commonCheckList,
-			resource.TestCheckResourceAttr(fqrn, "rules.0.criteria.0.cvss_range.0.from", tempStruct["cvss_from"]),
-			resource.TestCheckResourceAttr(fqrn, "rules.0.criteria.0.cvss_range.0.to", tempStruct["cvss_to"]),
+			resource.TestCheckResourceAttr(fqrn, "rule.0.criteria.0.cvss_range.0.from", tempStruct["cvss_from"]),
+			resource.TestCheckResourceAttr(fqrn, "rule.0.criteria.0.cvss_range.0.to", tempStruct["cvss_to"]),
 		)
 	}
 	if cvssOrSeverity == "severity" {
 		return resource.ComposeTestCheckFunc(
 			commonCheckList,
-			resource.TestCheckResourceAttr(fqrn, "rules.0.criteria.0.min_severity", tempStruct["min_severity"]),
+			resource.TestCheckResourceAttr(fqrn, "rule.0.criteria.0.min_severity", tempStruct["min_severity"]),
 		)
 	}
 	return nil
@@ -353,7 +333,7 @@ const securityPolicyCVSS = `resource "xray_security_policy" "{{ .resource_name }
 	name = "{{ .policy_name }}"
 	description = "{{ .policy_description }}"
 	type = "security"
-	rules {
+	rule {
 		name = "{{ .rule_name }}"
 		priority = 1
 		criteria {	
@@ -381,7 +361,7 @@ const securityPolicyMinSeverity = `resource "xray_security_policy" "{{ .resource
 	name = "{{ .policy_name }}"
 	description = "{{ .policy_description }}"
 	type = "security"
-	rules {
+	rule {
 		name = "{{ .rule_name }}"
 		priority = 1
 		criteria {
diff --git a/pkg/xray/resource_xray_watch_test.go b/pkg/xray/resource_xray_watch_test.go
new file mode 100644
index 00000000..d53ac10d
--- /dev/null
+++ b/pkg/xray/resource_xray_watch_test.go
@@ -0,0 +1,569 @@
+package xray
+
+import (
+	"fmt"
+	"testing"
+
+	"github.com/go-resty/resty/v2"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+var tempStructWatch = map[string]string{
+	"resource_name":     "",
+	"watch_name":        "xray-watch",
+	"description":       "This is a new watch created by TF Provider",
+	"active":            "true",
+	"watch_type":        "all-repos",
+	"filter_type_0":     "regex",
+	"filter_value_0":    ".*",
+	"filter_type_1":     "package-type",
+	"filter_value_1":    "Docker",
+	"policy_name_0":     "xray-policy-0",
+	"policy_name_1":     "xray-policy-1",
+	"watch_recipient_0": "test@email.com",
+	"watch_recipient_1": "test@email.com",
+}
+
+func TestAccWatch_allReposSinglePolicy(t *testing.T) {
+	_, fqrn, resourceName := mkNames("watch-", "xray_watch")
+	tempStruct := make(map[string]string)
+	copyStringMap(tempStructWatch, tempStruct)
+
+	tempStruct["resource_name"] = resourceName
+	tempStruct["watch_name"] = fmt.Sprintf("xray-watch-%d", randomInt())
+	tempStruct["policy_name_0"] = fmt.Sprintf("xray-policy-%d", randomInt())
+
+	resource.Test(t, resource.TestCase{
+		PreCheck: func() { testAccPreCheck(t) },
+		CheckDestroy: verifyDeleted(fqrn, func(id string, request *resty.Request) (*resty.Response, error) {
+			testCheckPolicyDeleted("xray_security_policy.security", t, request)
+			resp, err := testCheckWatch(id, request)
+			return resp, err
+		}),
+		ProviderFactories: testAccProviders(),
+		Steps: []resource.TestStep{
+			{
+				Config: executeTemplate(fqrn, allReposSinglePolicyWatchTemplate, tempStruct),
+				Check:  verifyXrayWatch(fqrn, tempStruct),
+			},
+		},
+	})
+}
+
+func TestAccWatch_allReposMultiplePolicies(t *testing.T) {
+	_, fqrn, resourceName := mkNames("watch-", "xray_watch")
+	tempStruct := make(map[string]string)
+	copyStringMap(tempStructWatch, tempStruct)
+
+	tempStruct["resource_name"] = resourceName
+	tempStruct["watch_name"] = fmt.Sprintf("xray-watch-%d", randomInt())
+	tempStruct["policy_name_0"] = fmt.Sprintf("xray-policy-1%d", randomInt())
+	tempStruct["policy_name_1"] = fmt.Sprintf("xray-policy-2%d", randomInt())
+
+	resource.Test(t, resource.TestCase{
+		PreCheck: func() { testAccPreCheck(t) },
+		CheckDestroy: verifyDeleted(fqrn, func(id string, request *resty.Request) (*resty.Response, error) {
+			testCheckPolicyDeleted("xray_security_policy.security", t, request)
+			testCheckPolicyDeleted("xray_license_policy.license", t, request)
+			resp, err := testCheckWatch(id, request)
+			return resp, err
+		}),
+
+		ProviderFactories: testAccProviders(),
+		Steps: []resource.TestStep{
+			{
+				Config: executeTemplate(fqrn, allReposMultiplePoliciesWatchTemplate, tempStruct),
+				Check: resource.ComposeTestCheckFunc(
+					resource.TestCheckResourceAttr(fqrn, "name", tempStruct["watch_name"]),
+					resource.TestCheckResourceAttr(fqrn, "description", tempStruct["description"]),
+					resource.TestCheckResourceAttr(fqrn, "watch_resource.0.type", tempStruct["watch_type"]),
+					resource.TestCheckResourceAttr(fqrn, "assigned_policy.0.name", tempStruct["policy_name_0"]),
+					resource.TestCheckResourceAttr(fqrn, "assigned_policy.0.type", "security"),
+					resource.TestCheckResourceAttr(fqrn, "assigned_policy.1.name", tempStruct["policy_name_1"]),
+					resource.TestCheckResourceAttr(fqrn, "assigned_policy.1.type", "license"),
+				),
+			},
+		},
+	})
+}
+
+// To verify the watch for a single repo we need to create a new repository with Xray indexing enabled
+// testAccCreateRepos() is creating a local repos with Xray indexing enabled using the API call
+// We need to figure out how to use external providers (like Artifactory) in the tests. Documented approach didn't work
+func TestAccWatch_singleRepository(t *testing.T) {
+	_, fqrn, resourceName := mkNames("watch-", "xray_watch")
+	tempStruct := make(map[string]string)
+	copyStringMap(tempStructWatch, tempStruct)
+
+	tempStruct["resource_name"] = resourceName
+	tempStruct["watch_name"] = fmt.Sprintf("xray-watch-%d", randomInt())
+	tempStruct["policy_name_0"] = fmt.Sprintf("xray-policy-%d", randomInt())
+	tempStruct["watch_type"] = "repository"
+	repo0 := "libs-release-local"
+	repo1 := "libs-release-local-1"
+
+	resource.Test(t, resource.TestCase{
+		PreCheck: func() {
+			testAccPreCheck(t)
+			testAccCreateRepos(t, repo0)
+			testAccCreateRepos(t, repo1)
+		},
+		CheckDestroy: verifyDeleted(fqrn, func(id string, request *resty.Request) (*resty.Response, error) {
+			testAccDeleteRepo(t, repo0)
+			testAccDeleteRepo(t, repo1)
+			testCheckPolicyDeleted("xray_security_policy.security", t, request)
+			resp, err := testCheckWatch(id, request)
+			return resp, err
+		}),
+
+		ProviderFactories: testAccProviders(),
+		Steps: []resource.TestStep{
+			{
+				Config: executeTemplate(fqrn, singleRepositoryWatchTemplate, tempStruct),
+				Check:  verifyXrayWatch(fqrn, tempStruct),
+			},
+		},
+	})
+}
+
+func TestAccWatch_multipleRepositories(t *testing.T) {
+	_, fqrn, resourceName := mkNames("watch-", "xray_watch")
+	tempStruct := make(map[string]string)
+	copyStringMap(tempStructWatch, tempStruct)
+
+	tempStruct["resource_name"] = resourceName
+	tempStruct["watch_name"] = fmt.Sprintf("xray-watch-%d", randomInt())
+	tempStruct["policy_name_0"] = fmt.Sprintf("xray-policy-%d", randomInt())
+	tempStruct["watch_type"] = "repository"
+	repo0 := "libs-release-local"
+	repo1 := "libs-release-local-1"
+
+	resource.Test(t, resource.TestCase{
+		PreCheck: func() {
+			testAccPreCheck(t)
+			testAccCreateRepos(t, repo0)
+			testAccCreateRepos(t, repo1)
+		},
+		CheckDestroy: verifyDeleted(fqrn, func(id string, request *resty.Request) (*resty.Response, error) {
+			testAccDeleteRepo(t, repo0)
+			testAccDeleteRepo(t, repo1)
+			testCheckPolicyDeleted("xray_security_policy.security", t, request)
+			resp, err := testCheckWatch(id, request)
+			return resp, err
+		}),
+		ProviderFactories: testAccProviders(),
+		Steps: []resource.TestStep{
+			{
+				Config: executeTemplate(fqrn, multipleRepositoriesWatchTemplate, tempStruct),
+				Check:  verifyXrayWatch(fqrn, tempStruct),
+			},
+		},
+	})
+}
+
+func TestAccWatch_build(t *testing.T) {
+	_, fqrn, resourceName := mkNames("watch-", "xray_watch")
+	tempStruct := make(map[string]string)
+	copyStringMap(tempStructWatch, tempStruct)
+
+	tempStruct["resource_name"] = resourceName
+	tempStruct["watch_name"] = fmt.Sprintf("xray-watch-%d", randomInt())
+	tempStruct["policy_name_0"] = fmt.Sprintf("xray-policy-%d", randomInt())
+	tempStruct["watch_type"] = "build"
+	tempStruct["build_name0"] = "release-pipeline"
+	tempStruct["build_name1"] = "release-pipeline1"
+	builds := []string{tempStruct["build_name0"]}
+
+	resource.Test(t, resource.TestCase{
+		PreCheck: func() {
+			testAccPreCheck(t)
+			testAccCreateBuilds(t, builds)
+		},
+		CheckDestroy:      verifyDeleted(fqrn, testCheckWatch),
+		ProviderFactories: testAccProviders(),
+		Steps: []resource.TestStep{
+			{
+				Config: executeTemplate(fqrn, buildWatchTemplate, tempStruct),
+				Check:  verifyXrayWatch(fqrn, tempStruct),
+			},
+		},
+	})
+}
+
+func TestAccWatch_multipleBuilds(t *testing.T) {
+	_, fqrn, resourceName := mkNames("watch-", "xray_watch")
+	tempStruct := make(map[string]string)
+	copyStringMap(tempStructWatch, tempStruct)
+
+	tempStruct["resource_name"] = resourceName
+	tempStruct["watch_name"] = fmt.Sprintf("xray-watch-%d", randomInt())
+	tempStruct["policy_name_0"] = fmt.Sprintf("xray-policy-%d", randomInt())
+	tempStruct["watch_type"] = "build"
+	tempStruct["build_name0"] = "release-pipeline"
+	tempStruct["build_name1"] = "release-pipeline1"
+	builds := []string{tempStruct["build_name0"], tempStruct["build_name1"]}
+
+	resource.Test(t, resource.TestCase{
+		PreCheck: func() {
+			testAccPreCheck(t)
+			testAccCreateBuilds(t, builds)
+		},
+		CheckDestroy:      verifyDeleted(fqrn, testCheckWatch),
+		ProviderFactories: testAccProviders(),
+		Steps: []resource.TestStep{
+			{
+				Config: executeTemplate(fqrn, multipleBuildsWatchTemplate, tempStruct),
+				Check:  verifyXrayWatch(fqrn, tempStruct),
+			},
+		},
+	})
+}
+
+const allReposSinglePolicyWatchTemplate = `resource "xray_security_policy" "security" {
+  name        = "{{ .policy_name_0 }}"
+  description = "Security policy description"
+  type        = "security"
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+    criteria {
+      min_severity = "High"
+    }
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_download {
+        unscanned = true
+        active    = true
+      }
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false  
+      build_failure_grace_period_in_days = 5   
+    }
+  }
+}
+
+resource "xray_watch" "{{ .resource_name }}" {
+  name        	= "{{ .watch_name }}"
+  description 	= "{{ .description }}"
+  active 		= {{ .active }}
+
+  watch_resource {
+	type       	= "{{ .watch_type }}"
+	filter {
+		type  	= "{{ .filter_type_0 }}"
+		value	= "{{ .filter_value_0 }}"
+	}
+}
+  assigned_policy {
+  	name 	= xray_security_policy.security.name
+  	type 	= "security"
+}
+
+  watch_recipients = ["{{ .watch_recipient_0 }}", "{{ .watch_recipient_1 }}"]
+}`
+
+const allReposMultiplePoliciesWatchTemplate = `resource "xray_security_policy" "security" {
+  name        = "{{ .policy_name_0 }}"
+  description = "Security policy description"
+  type        = "security"
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+    criteria {
+      min_severity = "High"
+    }
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_download {
+        unscanned = true
+        active    = true
+      }
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false  
+      build_failure_grace_period_in_days = 5   
+    }
+  }
+}
+
+resource "xray_license_policy" "license" {
+  name        = "{{ .policy_name_1 }}"
+  description = "License policy description"
+  type        = "license"
+  rule {
+    name     = "License_rule"
+    priority = 1
+    criteria {
+      allowed_licenses         = ["Apache-1.0", "Apache-2.0"]
+      allow_unknown            = false
+      multi_license_permissive = true
+    }
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_download {
+        unscanned = true
+        active    = true
+      }
+      block_release_bundle_distribution  = false
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false 
+      custom_severity                    = "High"
+      build_failure_grace_period_in_days = 5 
+    }
+  }
+}
+
+resource "xray_watch" "{{ .resource_name }}" {
+  name        	= "{{ .watch_name }}"
+  description 	= "{{ .description }}"
+  active 		= {{ .active }}
+
+  watch_resource {
+	type       	= "{{ .watch_type }}"
+	filter {
+		type  	= "{{ .filter_type_0 }}"
+		value	= "{{ .filter_value_0 }}"
+	}
+	filter {
+		type  	= "{{ .filter_type_1 }}"
+		value	= "{{ .filter_value_1 }}"
+	}
+}
+  assigned_policy {
+  	name 	= xray_security_policy.security.name
+  	type 	= "security"
+}
+  assigned_policy {
+  	name 	= xray_license_policy.license.name
+  	type 	= "license"
+}
+
+  watch_recipients = ["{{ .watch_recipient_0 }}", "{{ .watch_recipient_1 }}"]
+}`
+
+const singleRepositoryWatchTemplate = `resource "xray_security_policy" "security" {
+  name        = "{{ .policy_name_0 }}"
+  description = "Security policy description"
+  type        = "security"
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+    criteria {
+      min_severity = "High"
+    }
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_download {
+        unscanned = true
+        active    = true
+      }
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false  
+      build_failure_grace_period_in_days = 5   
+    }
+  }
+}
+
+resource "xray_watch" "{{ .resource_name }}" {
+  name        	= "{{ .watch_name }}"
+  description 	= "{{ .description }}"
+  active 		= {{ .active }}
+
+  watch_resource {
+	type       	= "{{ .watch_type }}"
+	bin_mgr_id  = "default"
+	name		= "libs-release-local"
+	filter {
+		type  	= "{{ .filter_type_0 }}"
+		value	= "{{ .filter_value_0 }}"
+	}
+}
+  assigned_policy {
+  	name 	= xray_security_policy.security.name
+  	type 	= "security"
+}
+  watch_recipients = ["{{ .watch_recipient_0 }}", "{{ .watch_recipient_1 }}"]
+}`
+
+const multipleRepositoriesWatchTemplate = `resource "xray_security_policy" "security" {
+  name        = "{{ .policy_name_0 }}"
+  description = "Security policy description"
+  type        = "security"
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+    criteria {
+      min_severity = "High"
+    }
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_download {
+        unscanned = true
+        active    = true
+      }
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false  
+      build_failure_grace_period_in_days = 5   
+    }
+  }
+}
+
+resource "xray_watch" "{{ .resource_name }}" {
+  name        	= "{{ .watch_name }}"
+  description 	= "{{ .description }}"
+  active 		= {{ .active }}
+
+  watch_resource {
+	type       	= "{{ .watch_type }}"
+	bin_mgr_id  = "default"
+	name		= "libs-release-local"
+	filter {
+		type  	= "{{ .filter_type_0 }}"
+		value	= "{{ .filter_value_0 }}"
+	}
+}
+  watch_resource {
+	type       	= "repository"
+	bin_mgr_id  = "default"
+	name		= "libs-release-local-1"
+	filter {
+		type  	= "{{ .filter_type_0 }}"
+		value	= "{{ .filter_value_0 }}"
+	}
+}
+  assigned_policy {
+  	name 	= xray_security_policy.security.name
+  	type 	= "security"
+}
+  watch_recipients = ["{{ .watch_recipient_0 }}", "{{ .watch_recipient_1 }}"]
+}`
+
+const buildWatchTemplate = `resource "xray_security_policy" "security" {
+  name        = "{{ .policy_name_0 }}"
+  description = "Security policy description"
+  type        = "security"
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+    criteria {
+      min_severity = "High"
+    }
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_download {
+        unscanned = true
+        active    = true
+      }
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false  
+      build_failure_grace_period_in_days = 5   
+    }
+  }
+}
+
+resource "xray_watch" "{{ .resource_name }}" {
+  name        	= "{{ .watch_name }}"
+  description 	= "{{ .description }}"
+  active 		= {{ .active }}
+
+  watch_resource {
+	type       	= "{{ .watch_type }}"
+	bin_mgr_id  = "default"
+	name		= "{{ .build_name0 }}"
+}
+  assigned_policy {
+  	name 	= xray_security_policy.security.name
+  	type 	= "security"
+}
+  watch_recipients = ["{{ .watch_recipient_0 }}", "{{ .watch_recipient_1 }}"]
+}`
+
+const multipleBuildsWatchTemplate = `resource "xray_security_policy" "security" {
+  name        = "{{ .policy_name_0 }}"
+  description = "Security policy description"
+  type        = "security"
+  rule {
+    name     = "rule-name-severity"
+    priority = 1
+    criteria {
+      min_severity = "High"
+    }
+    actions {
+      webhooks = []
+      mails    = ["test@email.com"]
+      block_download {
+        unscanned = true
+        active    = true
+      }
+      block_release_bundle_distribution  = true
+      fail_build                         = true
+      notify_watch_recipients            = true
+      notify_deployer                    = true
+      create_ticket_enabled              = false  
+      build_failure_grace_period_in_days = 5   
+    }
+  }
+}
+
+resource "xray_watch" "{{ .resource_name }}" {
+  name        	= "{{ .watch_name }}"
+  description 	= "{{ .description }}"
+  active 		= {{ .active }}
+
+  watch_resource {
+	type       	= "{{ .watch_type }}"
+	bin_mgr_id  = "default"
+	name		= "{{ .build_name0 }}"
+}
+
+  watch_resource {
+	type       	= "{{ .watch_type }}"
+	bin_mgr_id  = "default"
+	name		= "{{ .build_name1 }}"
+}
+  assigned_policy {
+  	name 	= xray_security_policy.security.name
+  	type 	= "security"
+}
+  watch_recipients = ["{{ .watch_recipient_0 }}", "{{ .watch_recipient_1 }}"]
+}`
+
+func verifyXrayWatch(fqrn string, tempStruct map[string]string) resource.TestCheckFunc {
+	return resource.ComposeTestCheckFunc(
+		resource.TestCheckResourceAttr(fqrn, "name", tempStruct["watch_name"]),
+		resource.TestCheckResourceAttr(fqrn, "description", tempStruct["description"]),
+		resource.TestCheckResourceAttr(fqrn, "watch_resource.0.type", tempStruct["watch_type"]),
+		resource.TestCheckResourceAttr(fqrn, "assigned_policy.0.name", tempStruct["policy_name_0"]),
+		resource.TestCheckResourceAttr(fqrn, "assigned_policy.0.type", "security"),
+	)
+}
+
+func checkWatch(id string, request *resty.Request) (*resty.Response, error) {
+	return request.Get("xray/api/v2/watches/" + id)
+}
+
+func testCheckWatch(id string, request *resty.Request) (*resty.Response, error) {
+	return checkWatch(id, request.AddRetryCondition(neverRetry))
+}
diff --git a/pkg/xray/util_test.go b/pkg/xray/util_test.go
index ef135192..006f3505 100644
--- a/pkg/xray/util_test.go
+++ b/pkg/xray/util_test.go
@@ -1,17 +1,23 @@
 package xray
 
 import (
+	"context"
 	"fmt"
-	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
 	"math"
+	"net/http"
 	"reflect"
 	"strings"
+	"testing"
+
+	"github.com/go-resty/resty/v2"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
 )
 
 func fmtMapToHcl(fields map[string]interface{}) string {
 	var allPairs []string
 	max := float64(0)
-	for key, _ := range fields {
+	for key := range fields {
 		max = math.Max(max, float64(len(key)))
 	}
 	for key, value := range fields {
@@ -76,3 +82,44 @@ func toHclFormat(thing interface{}) string {
 		return fmt.Sprintf("%v", thing)
 	}
 }
+
+func checkPolicy(id string, request *resty.Request) (*resty.Response, error) {
+	return request.Get("xray/api/v2/policies/" + id)
+}
+
+func testCheckPolicy(id string, request *resty.Request) (*resty.Response, error) {
+	return checkPolicy(id, request.AddRetryCondition(neverRetry))
+}
+
+func testCheckPolicyDeleted(id string, t *testing.T, request *resty.Request) *resty.Response {
+	_, err := checkPolicy(id, request.AddRetryCondition(neverRetry))
+	if err == nil {
+		t.Errorf("Policy %s still exists!", id)
+	}
+	return nil
+}
+
+type CheckFun func(id string, request *resty.Request) (*resty.Response, error)
+
+func verifyDeleted(id string, check CheckFun) func(*terraform.State) error {
+	return func(s *terraform.State) error {
+		rs, ok := s.RootModule().Resources[id]
+		if !ok {
+			return fmt.Errorf("error: Resource id [%s] not found", id)
+		}
+		provider, _ := testAccProviders()["xray"]()
+		provider.Configure(context.Background(), terraform.NewResourceConfigRaw(nil))
+		client := provider.Meta().(*resty.Client)
+		resp, err := check(rs.Primary.ID, client.R())
+		if err != nil {
+			if resp != nil {
+				switch resp.StatusCode() {
+				case http.StatusNotFound, http.StatusBadRequest, http.StatusInternalServerError:
+					return nil
+				}
+			}
+			return err
+		}
+		return fmt.Errorf("error: %s still exists", rs.Primary.ID)
+	}
+}