Project import generated by Copybara.
GitOrigin-RevId: 68e87652193f46ed70e5f6ec0100352f27baacd3
Change-Id: I11765970ccadcdfe57040dc4d4d1ebce65a92814
diff --git a/v0.10.0/.changes/0.10.0.md b/v0.10.0/.changes/0.10.0.md
new file mode 100644
index 0000000..8719a95
--- /dev/null
+++ b/v0.10.0/.changes/0.10.0.md
@@ -0,0 +1,6 @@
+## 0.10.0 (December 06, 2023)
+
+BUG FIXES:
+
+* resource/time_offset: Fix bug preventing multiple offset arguments from being set ([#189](https://github.com/hashicorp/terraform-provider-time/issues/189))
+
diff --git a/v0.10.0/.changes/0.9.1.md b/v0.10.0/.changes/0.9.1.md
new file mode 100644
index 0000000..ad53973
--- /dev/null
+++ b/v0.10.0/.changes/0.9.1.md
@@ -0,0 +1,94 @@
+## 0.9.1 (November 2, 2022)
+
+BUG FIXES:
+
+* resource/time_rotating: Correctly retrieve the Terraform state during update ([#132](https://github.com/hashicorp/terraform-provider-time/pull/132))
+
+## 0.9.0 (October 11, 2022)
+
+NOTES:
+
+* provider: Rewritten to use the new [`terraform-plugin-framework`](https://www.terraform.io/plugin/framework) ([#112](https://github.com/hashicorp/terraform-provider-time/pull/112))
+
+## 0.8.0 (August 10, 2022)
+
+BUG FIXES:
+
+* documentation: Changed wording from "Conflicts with other `offset_`/`rotation_` arguments." to "At least one of the `offset_`/`rotation_` arguments must be configured." to correctly reflect the use of `AtLeastOneOf` ([#105](https://github.com/hashicorp/terraform-provider-time/pull/105))
+
+NOTES:
+
+* provider: Upgrade Go version to 1.18 ([#114](https://github.com/hashicorp/terraform-provider-time/pull/114))
+* provider: Enable `golangci-lint` ([#105](https://github.com/hashicorp/terraform-provider-time/pull/105))
+
+## 0.7.2 (July 01, 2021)
+
+BUG FIXES:
+
+* resource/time_sleep: Prevent `context deadline exceeded` error when timeout duration is configured above 20 minutes ([#45](https://github.com/hashicorp/terraform-provider-time/issues/45))
+
+## 0.7.1 (May 04, 2021)
+
+BUG FIXES:
+
+* provider: Ensure `darwin/arm64` platform is included in releases
+
+## 0.7.0 (February 19, 2021)
+
+Binary releases of this provider now include the darwin-arm64 platform. This version contains no further changes.
+
+## 0.6.0 (October 04, 2020)
+
+BREAKING CHANGES:
+
+* Dropped support for Terraform 0.11 and lower ([#16](https://github.com/hashicorp/terraform-provider-time/issues/16))
+
+ENHANCEMENTS
+
+* Made `time_sleep` context aware, allowing easier early cancellation ([#16](https://github.com/hashicorp/terraform-provider-time/issues/16))
+
+## 0.5.0 (May 13, 2020)
+
+FEATURES
+
+* **New Resource:** `time_sleep` ([#12](https://github.com/hashicorp/terraform-provider-time/issues/12))
+
+# 0.4.0 (April 21, 2020)
+
+BREAKING CHANGES:
+
+* resource/time_offset: `keepers` argument renamed to `triggers`
+* resource/time_offset: Remove non-RFC3339 RFC and `unixdate` attribute
+* resource/time_rotating: `keepers` argument renamed to `triggers`
+* resource/time_rotating: Remove non-RFC3339 RFC and `unixdate` attributes
+* resource/time_static: `keepers` argument renamed to `triggers`
+* resource/time_static: Remove non-RFC3339 RFC and `unixdate` attributes
+
+# v0.3.0
+
+ENHANCEMENTS:
+
+* resource/time_offset: Add `keepers` argument
+* resource/time_rotating: Add `keepers` argument
+* resource/time_static: Add `keepers` argument
+
+BUG FIXES:
+
+* resource/time_offset: Ensure `base_rfc3339` is always set in Terraform state during creation, even if unconfigured
+
+# v0.2.0
+
+BREAKING CHANGES:
+
+* resource/time_static: The `expiration_` arguments have been moved to the new `time_rotating` resource as `rotation_` arguments.
+
+FEATURES:
+
+* **New Resource:** `time_offset`
+* **New Resource:** `time_rotating`
+
+# v0.1.0
+
+FEATURES:
+
+* **New Resource:** `time_static`
diff --git a/v0.10.0/.changes/0.9.2.md b/v0.10.0/.changes/0.9.2.md
new file mode 100644
index 0000000..92c2a5f
--- /dev/null
+++ b/v0.10.0/.changes/0.9.2.md
@@ -0,0 +1,6 @@
+## 0.9.2 (November 28, 2023)
+
+NOTES:
+
+* This release introduces no functional changes. It does however include dependency updates which address upstream CVEs. ([#263](https://github.com/hashicorp/terraform-provider-time/issues/263))
+
diff --git a/v0.10.0/.changes/unreleased/.gitkeep b/v0.10.0/.changes/unreleased/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/v0.10.0/.changes/unreleased/.gitkeep
diff --git a/v0.10.0/.changie.yaml b/v0.10.0/.changie.yaml
new file mode 100644
index 0000000..72541ae
--- /dev/null
+++ b/v0.10.0/.changie.yaml
@@ -0,0 +1,23 @@
+changesDir: .changes
+unreleasedDir: unreleased
+changelogPath: CHANGELOG.md
+versionExt: md
+versionFormat: '## {{.Version}} ({{.Time.Format "January 02, 2006"}})'
+kindFormat: '{{.Kind}}:'
+changeFormat: '* {{.Body}} ([#{{.Custom.Issue}}](https://github.com/hashicorp/terraform-provider-time/issues/{{.Custom.Issue}}))'
+custom:
+ - key: Issue
+ label: Issue/PR Number
+ type: int
+ minInt: 1
+kinds:
+ - label: BREAKING CHANGES
+ - label: NOTES
+ - label: FEATURES
+ - label: ENHANCEMENTS
+ - label: BUG FIXES
+newlines:
+ afterKind: 1
+ beforeKind: 1
+ endOfVersion: 2
+
diff --git a/v0.10.0/.copywrite.hcl b/v0.10.0/.copywrite.hcl
new file mode 100644
index 0000000..849ec77
--- /dev/null
+++ b/v0.10.0/.copywrite.hcl
@@ -0,0 +1,30 @@
+schema_version = 1
+
+project {
+ license = "MPL-2.0"
+ copyright_year = 2020
+
+ header_ignore = [
+ # changie tooling configuration and CHANGELOG entries (prose)
+ ".changes/unreleased/*.yaml",
+ ".changie.yaml",
+
+ # examples used within documentation (prose)
+ "examples/**",
+
+ # GitHub issue template configuration
+ ".github/ISSUE_TEMPLATE/*.yml",
+
+ # GitHub Actions workflow-specific configurations
+ ".github/labeler-*.yml",
+
+ # golangci-lint tooling configuration
+ ".golangci.yml",
+
+ # GoReleaser tooling configuration
+ ".goreleaser.yml",
+
+ # Release Engineering tooling configuration
+ ".release/*.hcl",
+ ]
+}
diff --git a/v0.10.0/.github/CODEOWNERS b/v0.10.0/.github/CODEOWNERS
new file mode 100644
index 0000000..922ee27
--- /dev/null
+++ b/v0.10.0/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @hashicorp/terraform-devex
diff --git a/v0.10.0/.github/CONTRIBUTING.md b/v0.10.0/.github/CONTRIBUTING.md
new file mode 100644
index 0000000..583406b
--- /dev/null
+++ b/v0.10.0/.github/CONTRIBUTING.md
@@ -0,0 +1,149 @@
+# Contributing
+
+Thank you for investing your time and energy by contributing to our project: please ensure you are familiar
+with the [HashiCorp Code of Conduct](https://github.com/hashicorp/.github/blob/master/CODE_OF_CONDUCT.md).
+
+This provider is a HashiCorp **utility provider**, which means any bug fix and feature
+has to be considered in the context of the thousands/millions of configurations in which this provider is used.
+This is great as your contribution can have a big positive impact, but we have to assess potential negative impact too
+(e.g. breaking existing configurations). _Stability over features_.
+
+To provide some safety to the wider provider ecosystem, we strictly follow
+[semantic versioning](https://semver.org/) and HashiCorp's own
+[versioning specification](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#versioning-specification).
+Any changes that could be considered as breaking will only be included as part of a major release.
+In case multiple breaking changes need to happen, we will group them in the next upcoming major release.
+
+## Asking Questions
+
+For questions, curiosity, or if still unsure what you are dealing with,
+please see the HashiCorp [Terraform Providers Discuss](https://discuss.hashicorp.com/c/terraform-providers/31)
+forum.
+
+## Reporting Vulnerabilities
+
+Please disclose security vulnerabilities responsibly by following the
+[HashiCorp Vulnerability Reporting guidelines](https://www.hashicorp.com/security#vulnerability-reporting).
+
+## Understanding the design
+
+Before proceeding with raising issues or submitting pull requests, it will probably help to familiarise yourself with
+the [design principles](../DESIGN.md) of this provider. This will aid your proposals, and help understand
+why we took certain decisions during development.
+
+## Raising Issues
+
+We welcome issues of all kinds including feature requests, bug reports or documentation suggestions.
+Below are guidelines for well-formed issues of each type.
+
+### Bug Reports
+
+* [ ] **Test against latest release**: Make sure you test against the latest available version of Terraform and the provider.
+ It is possible we may have already fixed the bug you're experiencing.
+* [ ] **Search for duplicates**: It's helpful to keep bug reports consolidated to one thread, so do a quick search
+ on existing bug reports to check if anybody else has reported the same thing.
+ You can scope searches by the label `bug` to help narrow things down.
+* [ ] **Include steps to reproduce**: Provide steps to reproduce the issue, along with code examples and/or real code,
+ so we can try to reproduce it. Without this, it makes it much harder (sometimes impossible) to fix the issue.
+
+### Feature Requests
+
+* [ ] **Search for possible duplicate requests**: It's helpful to keep requests consolidated to one thread,
+ so do a quick search on existing requests to check if anybody else has reported the same thing.
+ You can scope searches by the label `enhancement` to help narrow things down.
+* [ ] **Include a use case description**: In addition to describing the behavior of the feature you'd like to see added,
+ it's helpful to also make a case for why the feature would be important and how it would benefit
+ the provider and, potentially, the wider Terraform ecosystem.
+
+## New Pull Request
+
+Thank you for contributing!
+
+We are happy to review pull requests without associated issues,
+but we **highly recommend** starting by describing and discussing
+your problem or feature and attaching use cases to an issue first
+before raising a pull request.
+
+* [ ] **Early validation of idea and implementation plan**: provider development is complicated enough that there
+ are often several ways to implement something, each of which has different implications and tradeoffs.
+ Working through a plan of attack with the team before you dive into implementation will help ensure that you're
+ working in the right direction.
+* [ ] **Tests**: It may go without saying, but every new patch should be covered by tests wherever possible.
+ For bug-fixes, tests to prove the fix is valid. For features, tests to exercise the new code paths.
+* [ ] **Go Modules**: We use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage and version our dependencies.
+ Please make sure that you reflect dependency changes in your pull requests appropriately
+ (e.g. `go get`, `go mod tidy` or other commands).
+ Refer to the [dependency updates](#dependency-updates) section for more information about how
+ this project maintains existing dependencies.
+* [ ] **Changelog**: Refer to the [changelog](#changelog) section for more information about how to create changelog entries.
+* [ ] **License Headers**: All source code requires a license header at the top of the file, refer to [License Headers](#license-headers) for information on how to autogenerate these headers.
+
+### Dependency Updates
+
+Dependency management is performed by [Dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates).
+Where possible, dependency updates should occur through that system to ensure all Go module files are appropriately
+updated and to prevent duplicated effort of concurrent update submissions.
+Once available, updates are expected to be verified and merged to prevent latent technical debt.
+
+### Changelog
+
+HashiCorp’s open-source projects have always maintained user-friendly, readable `CHANGELOG`s that allow
+practitioners and developers to tell at a glance whether a release should have any effect on them,
+and to gauge the risk of an upgrade.
+
+We follow Terraform Plugin
+[changelog specifications](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#changelog-specification).
+
+#### Changie Automation Tool
+This provider uses the [Changie](https://changie.dev/) automation tool for changelog automation.
+To add a new entry to the `CHANGELOG` install Changie using the following [instructions](https://changie.dev/guide/installation/)
+and run
+```bash
+changie new
+```
+then choose a `kind` of change corresponding to the Terraform Plugin [changelog categories](https://developer.hashicorp.com/terraform/plugin/sdkv2/best-practices/versioning#categorization)
+and then fill out the body following the entry format. Changie will then prompt for a Github issue or pull request number.
+Repeat this process for any additional changes. The `.yaml` files created in the `.changes/unreleased` folder
+should be pushed the repository along with any code changes.
+
+#### Entry format
+
+Entries that are specific to _resources_ or _data sources_, they should look like:
+
+```markdown
+* resource/RESOURCE_NAME: ENTRY DESCRIPTION
+
+* data-source/DATA-SOURCE_NAME: ENTRY DESCRIPTION
+```
+
+#### Pull Request Types to `CHANGELOG`
+
+The `CHANGELOG` is intended to show developer-impacting changes to the codebase for a particular version.
+If every change or commit to the code resulted in an entry, the `CHANGELOG` would become less useful for developers.
+The lists below are general guidelines to decide whether a change should have an entry.
+
+##### Changes that should not have a `CHANGELOG` entry
+
+* Documentation updates
+* Testing updates
+* Code refactoring
+
+##### Changes that may have a `CHANGELOG` entry
+
+* Dependency updates: If the update contains relevant bug fixes or enhancements that affect developers,
+ those should be called out.
+
+##### Changes that should have a `CHANGELOG` entry
+
+* Major features
+* Bug fixes
+* Enhancements
+* Deprecations
+* Breaking changes and removals
+
+
+### License Headers
+
+All source code files (excluding autogenerated files like `go.mod`, prose, and files excluded in [.copywrite.hcl](../.copywrite.hcl)) must have a license header at the top.
+
+This can be autogenerated by running `make generate` or running `go generate ./...` in the [/tools](../tools) directory.
diff --git a/v0.10.0/.github/ISSUE_TEMPLATE/Bug_Report.yml b/v0.10.0/.github/ISSUE_TEMPLATE/Bug_Report.yml
new file mode 100644
index 0000000..6227a8e
--- /dev/null
+++ b/v0.10.0/.github/ISSUE_TEMPLATE/Bug_Report.yml
@@ -0,0 +1,85 @@
+name: Bug Report
+description: Something is incorrect or not working as expected.
+labels: ["bug"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for taking the time to fill out this bug report! Please note that this issue tracker is only used for bug reports and feature requests. Other issues will be closed.
+
+ If you have a configuration, workflow, or other question, please go back to the issue chooser and select one of the question links.
+ - type: textarea
+ id: versions
+ attributes:
+ label: Terraform CLI and Provider Versions
+ description: What versions of Terraform CLI and the provider?
+ placeholder: Output of `terraform version` from configuration directory
+ validations:
+ required: true
+ - type: textarea
+ id: terraform-configuration
+ attributes:
+ label: Terraform Configuration
+ description: Please copy and paste any relevant Terraform configuration. This will be automatically formatted into code, so no need for backticks.
+ render: terraform
+ validations:
+ required: true
+ - type: textarea
+ id: expected-behavior
+ attributes:
+ label: Expected Behavior
+ description: What did you expect to happen?
+ placeholder: Description of what should have happened.
+ validations:
+ required: true
+ - type: textarea
+ id: actual-behavior
+ attributes:
+ label: Actual Behavior
+ description: What actually happened?
+ placeholder: Description of what actually happened.
+ validations:
+ required: true
+ - type: textarea
+ id: reproduction-steps
+ attributes:
+ label: Steps to Reproduce
+ description: List of steps to reproduce the issue.
+ value: |
+ 1. `terraform apply`
+ validations:
+ required: true
+ - type: dropdown
+ id: impact
+ attributes:
+ label: How much impact is this issue causing?
+ description: High represents completely not able to use the provider or unexpected destruction of data/infrastructure. Medium represents unable to upgrade provider version or an issue with potential workaround. Low represents minor provider code, configuration, or documentation issues.
+ options:
+ - High
+ - Medium
+ - Low
+ validations:
+ required: true
+ - type: input
+ id: logs
+ attributes:
+ label: Logs
+ description: Please provide a link to a [GitHub Gist](https://gist.github.com) containing TRACE log output. [Terraform Debugging Documentation](https://www.terraform.io/internals/debugging)
+ placeholder: https://gist.github.com/example/12345678
+ validations:
+ required: false
+ - type: textarea
+ id: additional-information
+ attributes:
+ label: Additional Information
+ description: Are there any additional details about your environment, workflow, or recent changes that might be relevant? Have you discovered a workaround? Are there links to other related issues?
+ validations:
+ required: false
+ - type: checkboxes
+ id: terms
+ attributes:
+ label: Code of Conduct
+ description: By submitting this issue, you agree to follow our [Community Guidelines](https://www.hashicorp.com/community-guidelines).
+ options:
+ - label: I agree to follow this project's Code of Conduct
+ required: true
diff --git a/v0.10.0/.github/ISSUE_TEMPLATE/Feature_Request.yml b/v0.10.0/.github/ISSUE_TEMPLATE/Feature_Request.yml
new file mode 100644
index 0000000..275c48e
--- /dev/null
+++ b/v0.10.0/.github/ISSUE_TEMPLATE/Feature_Request.yml
@@ -0,0 +1,60 @@
+name: Feature Request
+description: Something is missing or could be improved.
+labels: ["enhancement"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thank you for taking the time to fill out this feature request! Please note that this issue tracker is only used for bug reports and feature requests. Other issues will be closed.
+
+ If you have a configuration, workflow, or other question, please go back to the issue chooser and select one of the question links.
+ - type: textarea
+ id: versions
+ attributes:
+ label: Terraform CLI and Provider Versions
+ description: What versions of Terraform CLI and the provider?
+ placeholder: Output of `terraform version` from configuration directory
+ validations:
+ required: true
+ - type: textarea
+ id: use-case
+ attributes:
+ label: Use Cases or Problem Statement
+ description: What use cases or problems are you trying to solve?
+ placeholder: Description of use cases or problems.
+ validations:
+ required: true
+ - type: textarea
+ id: proposal
+ attributes:
+ label: Proposal
+ description: What solutions would you prefer?
+ placeholder: Description of proposed solutions.
+ validations:
+ required: true
+ - type: dropdown
+ id: impact
+ attributes:
+ label: How much impact is this issue causing?
+ description: High represents completely not able to use the provider without this. Medium represents unable to solve a specific problem or understand something. Low represents minor provider code, configuration, or documentation issues.
+ options:
+ - High
+ - Medium
+ - Low
+ validations:
+ required: true
+ - type: textarea
+ id: additional-information
+ attributes:
+ label: Additional Information
+ description: Are there any additional details about your environment, workflow, or recent changes that might be relevant? Have you discovered a workaround? Are there links to other related issues?
+ validations:
+ required: false
+ - type: checkboxes
+ id: terms
+ attributes:
+ label: Code of Conduct
+ description: By submitting this issue, you agree to follow our [Community Guidelines](https://www.hashicorp.com/community-guidelines).
+ options:
+ - label: I agree to follow this project's Code of Conduct
+ required: true
diff --git a/v0.10.0/.github/ISSUE_TEMPLATE/config.yml b/v0.10.0/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..cd2c84d
--- /dev/null
+++ b/v0.10.0/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Terraform Provider Questions
+ url: https://discuss.hashicorp.com/c/terraform-providers/31
+ about: GitHub issues in this repository are only intended for bug reports and feature requests. Other issues will be closed. Please ask and answer questions through the Terraform Provider section of HashiCorp Discuss.
+ - name: Terraform Language or Workflow Questions
+ url: https://discuss.hashicorp.com/c/terraform-core
+ about: Please ask and answer language or workflow related questions through the Terraform Core section of HashiCorp Discuss.
diff --git a/v0.10.0/.github/PULL_REQUEST_TEMPLATE.md b/v0.10.0/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..b42cf78
--- /dev/null
+++ b/v0.10.0/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,11 @@
+<!--- Please keep this note for the community --->
+
+### Community Note
+
+* Please vote on this pull request by adding a 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to the original pull request comment to help the community and maintainers prioritize this request
+* Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for pull request followers and do not help prioritize the request
+
+<!--- Thank you for keeping this note for the community --->
+
+<!--- If your PR fully resolves and should automatically close the linked issue, use Closes. Otherwise, use Relates --->
+Relates OR Closes #0000
diff --git a/v0.10.0/.github/SUPPORT.md b/v0.10.0/.github/SUPPORT.md
new file mode 100644
index 0000000..5310957
--- /dev/null
+++ b/v0.10.0/.github/SUPPORT.md
@@ -0,0 +1,6 @@
+# Support
+
+* Project [README](../README.md)
+* Official [Documentation](https://registry.terraform.io/providers/hashicorp/time/latest/docs)
+* Providers [Discuss forums](https://discuss.hashicorp.com/c/terraform-providers/31)
+* Terraform [Community](https://www.terraform.io/community.html) page
\ No newline at end of file
diff --git a/v0.10.0/.github/dependabot.yml b/v0.10.0/.github/dependabot.yml
new file mode 100644
index 0000000..a785244
--- /dev/null
+++ b/v0.10.0/.github/dependabot.yml
@@ -0,0 +1,14 @@
+# See GitHub's docs for more information on this file:
+# https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates
+version: 2
+updates:
+ # Maintain dependencies for Go modules
+ - package-ecosystem: "gomod"
+ directory: "/"
+ schedule:
+ # Check for updates to Go modules every weekday
+ interval: "daily"
+ - package-ecosystem: "gomod"
+ directory: "/tools"
+ schedule:
+ interval: "daily"
diff --git a/v0.10.0/.github/labeler-issue-triage.yml b/v0.10.0/.github/labeler-issue-triage.yml
new file mode 100644
index 0000000..d1a51fd
--- /dev/null
+++ b/v0.10.0/.github/labeler-issue-triage.yml
@@ -0,0 +1,4 @@
+bug:
+ - 'panic:'
+crash:
+ - 'panic:'
diff --git a/v0.10.0/.github/labeler-pull-request-triage.yml b/v0.10.0/.github/labeler-pull-request-triage.yml
new file mode 100644
index 0000000..31375c0
--- /dev/null
+++ b/v0.10.0/.github/labeler-pull-request-triage.yml
@@ -0,0 +1,6 @@
+dependencies:
+ - .github/dependabot.yml
+ - go.mod
+ - go.sum
+documentation:
+ - website/**/*
diff --git a/v0.10.0/.github/workflows/add-content-to-project.yml b/v0.10.0/.github/workflows/add-content-to-project.yml
new file mode 100644
index 0000000..35166f2
--- /dev/null
+++ b/v0.10.0/.github/workflows/add-content-to-project.yml
@@ -0,0 +1,40 @@
+# Based on https://github.com/leonsteinhaeuser/project-beta-automations
+
+name: "Add Issues/PRs to TF Provider DevEx team board"
+
+on:
+ issues:
+ types: [opened, reopened]
+ pull_request_target:
+ # NOTE: The way content is added to project board is equivalent to an "upsert".
+ # Calling it multiple times will be idempotent.
+ #
+ # See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
+ # to see the reasoning behind using `pull_request_target` instead of `pull_request`
+ types: [opened, reopened, ready_for_review]
+
+jobs:
+ add-content-to-project:
+ name: "Add Content to project"
+ runs-on: ubuntu-latest
+ steps:
+ - name: "Set Issue to 'Priority = Triage Next'"
+ uses: leonsteinhaeuser/project-beta-automations@939000fb1900c9fc4f7b5058a09d9f833ebc6859 # v2.2.1
+ if: github.event_name == 'issues'
+ with:
+ gh_token: ${{ secrets.TF_DEVEX_PROJECT_GITHUB_TOKEN }}
+ organization: "hashicorp"
+ project_id: 99 #< https://github.com/orgs/hashicorp/projects/99
+ resource_node_id: ${{ github.event.issue.node_id }}
+ operation_mode: custom_field
+ custom_field_values: '[{\"name\":\"Priority\",\"type\":\"single_select\",\"value\":\"Triage Next\"}]'
+ - name: "Set Pull Request to 'Priority = Triage Next'"
+ uses: leonsteinhaeuser/project-beta-automations@939000fb1900c9fc4f7b5058a09d9f833ebc6859 # v2.2.1
+ if: github.event_name == 'pull_request_target'
+ with:
+ gh_token: ${{ secrets.TF_DEVEX_PROJECT_GITHUB_TOKEN }}
+ organization: "hashicorp"
+ project_id: 99 #< https://github.com/orgs/hashicorp/projects/99
+ resource_node_id: ${{ github.event.pull_request.node_id }}
+ operation_mode: custom_field
+ custom_field_values: '[{\"name\":\"Priority\",\"type\":\"single_select\",\"value\":\"Triage Next\"}]'
diff --git a/v0.10.0/.github/workflows/ci-changie.yml b/v0.10.0/.github/workflows/ci-changie.yml
new file mode 100644
index 0000000..8ec8b11
--- /dev/null
+++ b/v0.10.0/.github/workflows/ci-changie.yml
@@ -0,0 +1,23 @@
+# Continuous integration handling for changie
+name: ci-changie
+
+on:
+ pull_request:
+ paths:
+ - .changes/unreleased/*.yaml
+ - .changie.yaml
+ - .github/workflows/ci-changie.yml
+
+permissions:
+ contents: read
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: miniscruff/changie-action@6dcc2533cac0495148ed4046c438487e4dceaa23 # v2.0.0
+ with:
+ version: latest
+ args: batch patch --dry-run
+
diff --git a/v0.10.0/.github/workflows/compliance.yml b/v0.10.0/.github/workflows/compliance.yml
new file mode 100644
index 0000000..4be40b1
--- /dev/null
+++ b/v0.10.0/.github/workflows/compliance.yml
@@ -0,0 +1,17 @@
+name: compliance
+
+on:
+ pull_request:
+
+permissions:
+ contents: read
+
+jobs:
+ # Reference: ENGSRV-059
+ copywrite:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: hashicorp/setup-copywrite@867a1a2a064a0626db322392806428f7dc59cb3e # v1.1.2
+ - run: copywrite headers --plan
+ - run: copywrite license --plan
diff --git a/v0.10.0/.github/workflows/issue-comment-created.yml b/v0.10.0/.github/workflows/issue-comment-created.yml
new file mode 100644
index 0000000..0c4f898
--- /dev/null
+++ b/v0.10.0/.github/workflows/issue-comment-created.yml
@@ -0,0 +1,15 @@
+name: Issue Comment Created Triage
+
+on:
+ issue_comment:
+ types: [created]
+
+jobs:
+ issue_comment_triage:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions-ecosystem/action-remove-labels@2ce5d41b4b6aa8503e285553f75ed56e0a40bae0 # v1.3.0
+ with:
+ labels: |
+ stale
+ waiting-response
diff --git a/v0.10.0/.github/workflows/issue-opened.yml b/v0.10.0/.github/workflows/issue-opened.yml
new file mode 100644
index 0000000..3dac637
--- /dev/null
+++ b/v0.10.0/.github/workflows/issue-opened.yml
@@ -0,0 +1,16 @@
+name: Issue Opened Triage
+
+on:
+ issues:
+ types: [opened]
+
+jobs:
+ issue_triage:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: github/issue-labeler@6bea9ed491bb74fce38775b3d863e64a59dbd9eb # v3.3
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
+ configuration-path: .github/labeler-issue-triage.yml
+ enable-versioned-regex: 0
diff --git a/v0.10.0/.github/workflows/jira-sync.yml b/v0.10.0/.github/workflows/jira-sync.yml
new file mode 100644
index 0000000..737d56a
--- /dev/null
+++ b/v0.10.0/.github/workflows/jira-sync.yml
@@ -0,0 +1,39 @@
+on:
+ issues:
+ types: [closed, deleted, reopened]
+ pull_request_target:
+ types: [closed, reopened]
+
+name: Jira Sync
+
+jobs:
+ sync:
+ runs-on: ubuntu-latest
+ name: Jira sync
+ steps:
+
+ - name: Login
+ uses: atlassian/gajira-login@45fd029b9f1d6d8926c6f04175aa80c0e42c9026 # v3.0.1
+ if: contains(github.event.pull_request.labels.*.name, 'tf-devex-triage') || contains(github.event.issue.labels.*.name, 'tf-devex-triage')
+ env:
+ JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
+ JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
+ JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
+ - name: Search for existing issue
+ id: search
+ if: contains(github.event.pull_request.labels.*.name, 'tf-devex-triage') || contains(github.event.issue.labels.*.name, 'tf-devex-triage')
+ uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2
+ with:
+ jql: 'project="TFECO" and "Team (R&D)[Labels]"="TF-DevEx" and description ~ "${{ github.event.issue.html_url || github.event.pull_request.html_url }}" and labels in (Github)'
+ - name: Close task
+ if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue
+ uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1
+ with:
+ issue: ${{ steps.search.outputs.issue }}
+ transition: "Closed"
+ - name: Reopen task
+ if: github.event.action == 'reopened' && steps.search.outputs.issue
+ uses: atlassian/gajira-transition@38fc9cd61b03d6a53dd35fcccda172fe04b36de3 # v3.0.1
+ with:
+ issue: ${{ steps.search.outputs.issue }}
+ transition: "To Do"
diff --git a/v0.10.0/.github/workflows/pull-request.yml b/v0.10.0/.github/workflows/pull-request.yml
new file mode 100644
index 0000000..ef73062
--- /dev/null
+++ b/v0.10.0/.github/workflows/pull-request.yml
@@ -0,0 +1,31 @@
+name: "Pull Request Triage"
+
+on: [pull_request_target]
+
+permissions:
+ # CodelyTV/pr-size-labeler uses issues URL for labeling
+ issues: write
+ pull-requests: write
+
+jobs:
+ triage:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0
+ with:
+ configuration-path: .github/labeler-pull-request-triage.yml
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
+ - uses: CodelyTV/pr-size-labeler@54ef36785e9f4cb5ecf1949cfc9b00dbb621d761 # v1.8.1
+ with:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ xs_label: 'size/XS'
+ xs_max_size: '30'
+ s_label: 'size/S'
+ s_max_size: '60'
+ m_label: 'size/M'
+ m_max_size: '150'
+ l_label: 'size/L'
+ l_max_size: '300'
+ xl_label: 'size/XL'
+ message_if_xl: ''
+ files_to_ignore: 'go.sum'
diff --git a/v0.10.0/.github/workflows/release.yml b/v0.10.0/.github/workflows/release.yml
new file mode 100644
index 0000000..611d2e5
--- /dev/null
+++ b/v0.10.0/.github/workflows/release.yml
@@ -0,0 +1,118 @@
+name: Release
+
+on:
+ workflow_dispatch:
+ inputs:
+ versionNumber:
+ description: 'Release version number (v#.#.#)'
+ type: string
+ required: true
+
+permissions:
+ contents: read # Changelog commit operations use service account PAT
+
+jobs:
+ changelog-version:
+ runs-on: ubuntu-latest
+ outputs:
+ version: ${{ steps.changelog-version.outputs.version }}
+ steps:
+ - id: changelog-version
+ run: echo "version=$(echo "${{ inputs.versionNumber }}" | cut -c 2-)" >> "$GITHUB_OUTPUT"
+
+ changelog:
+ needs: changelog-version
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ fetch-depth: 0
+ # Avoid persisting GITHUB_TOKEN credentials as they take priority over our service account PAT for `git push` operations
+ # More details: https://github.com/actions/checkout/blob/b4626ce19ce1106186ddf9bb20e706842f11a7c3/adrs/0153-checkout-v2.md#persist-credentials
+ persist-credentials: false
+
+ - name: Batch changes
+ uses: miniscruff/changie-action@6dcc2533cac0495148ed4046c438487e4dceaa23 # v2.0.0
+ with:
+ version: latest
+ args: batch ${{ needs.changelog-version.outputs.version }}
+
+ - name: Merge changes
+ uses: miniscruff/changie-action@6dcc2533cac0495148ed4046c438487e4dceaa23 # v2.0.0
+ with:
+ version: latest
+ args: merge
+
+ - name: Git push changelog
+ run: |
+ git config --global user.name "${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}"
+ git config --global user.email "${{ vars.TF_DEVEX_CI_COMMIT_EMAIL }}"
+ git add .
+ git commit -a -m "Update changelog"
+ git push "https://${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}:${{ secrets.TF_DEVEX_COMMIT_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
+
+ release-tag:
+ needs: changelog
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ fetch-depth: 0
+ # Default input is the SHA that initially triggered the workflow. As we created a new commit in the previous job,
+ # to ensure we get the latest commit we use the ref for checkout: 'refs/heads/<branch_name>'
+ ref: ${{ github.ref }}
+ # Avoid persisting GITHUB_TOKEN credentials as they take priority over our service account PAT for `git push` operations
+ # More details: https://github.com/actions/checkout/blob/b4626ce19ce1106186ddf9bb20e706842f11a7c3/adrs/0153-checkout-v2.md#persist-credentials
+ persist-credentials: false
+
+ - name: Git push release tag
+ run: |
+ git config --global user.name "${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}"
+ git config --global user.email "${{ vars.TF_DEVEX_CI_COMMIT_EMAIL }}"
+
+ git tag "${{ inputs.versionNumber }}"
+ git push "https://${{ vars.TF_DEVEX_CI_COMMIT_AUTHOR }}:${{ secrets.TF_DEVEX_COMMIT_GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" "${{ inputs.versionNumber }}"
+
+ release-notes:
+ needs: [ changelog-version, changelog, release-tag ]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ inputs.versionNumber }}
+ fetch-depth: 0
+
+ - name: Generate Release Notes
+ run: |
+ cd .changes
+ sed -e "1{/# /d;}" -e "2{/^$/d;}" ${{ needs.changelog-version.outputs.version }}.md > release-notes.txt
+
+ - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
+ with:
+ name: release-notes
+ path: ./.changes/release-notes.txt
+ retention-days: 1
+
+ terraform-provider-release:
+ name: 'Terraform Provider Release'
+ needs: [ release-notes ]
+ permissions:
+ contents: write # Needed for goreleaser to create GitHub release
+ uses: hashicorp/ghaction-terraform-provider-release/.github/workflows/hashicorp.yml@01981baad5d35ce2342924e60ae91cf69fe31fd0 # v2.3.0
+ secrets:
+ hc-releases-key-prod: '${{ secrets.HC_RELEASES_KEY_PROD }}'
+ hc-releases-key-staging: '${{ secrets.HC_RELEASES_KEY_STAGING }}'
+ hc-releases-github-token: '${{ secrets.HASHI_RELEASES_GITHUB_TOKEN }}'
+ hc-releases-terraform-registry-sync-token: '${{ secrets.TF_PROVIDER_RELEASE_TERRAFORM_REGISTRY_SYNC_TOKEN }}'
+ setup-signore-github-token: '${{ secrets.HASHI_SIGNORE_GITHUB_TOKEN }}'
+ signore-client-id: '${{ secrets.SIGNORE_CLIENT_ID }}'
+ signore-client-secret: '${{ secrets.SIGNORE_CLIENT_SECRET }}'
+ hc-releases-host-staging: '${{ secrets.HC_RELEASES_HOST_STAGING }}'
+ hc-releases-host-prod: '${{ secrets.HC_RELEASES_HOST_PROD }}'
+ with:
+ release-notes: true
+ setup-go-version-file: 'go.mod'
+ # Product Version (e.g. v1.2.3)
+ product-version: '${{ inputs.versionNumber }}'
diff --git a/v0.10.0/.github/workflows/send-to-jira.yml b/v0.10.0/.github/workflows/send-to-jira.yml
new file mode 100644
index 0000000..cee84f6
--- /dev/null
+++ b/v0.10.0/.github/workflows/send-to-jira.yml
@@ -0,0 +1,37 @@
+on:
+ issues:
+ types: [labeled]
+
+name: Jira Sync
+
+jobs:
+ sync:
+ runs-on: ubuntu-latest
+ name: Jira sync
+ steps:
+
+ - name: Login
+ uses: atlassian/gajira-login@45fd029b9f1d6d8926c6f04175aa80c0e42c9026 # v3.0.1
+ if: github.event.label.name == 'tf-devex-triage'
+ env:
+ JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
+ JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
+ JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
+ - name: Search for existing issue
+ id: search
+ if: github.event.label.name == 'tf-devex-triage'
+ uses: tomhjp/gh-action-jira-search@04700b457f317c3e341ce90da5a3ff4ce058f2fa # v0.2.2
+ with:
+ jql: 'project="TFECO" and "Team (R&D)[Labels]"="TF-DevEx" and description ~ "${{ github.event.issue.html_url || github.event.pull_request.html_url }}" and labels in (Github)'
+
+ - name: Create task in DevEx board
+ if: github.event.label.name == 'tf-devex-triage' && !steps.search.outputs.issue
+ uses: atlassian/gajira-create@59e177c4f6451399df5b4911c2211104f171e669 # v3.0.1
+ with:
+ project: TFECO
+ issuetype: "Task"
+ summary: "[GH] ${{ github.event.issue.title || github.event.pull_request.title }}"
+ description: "${{ github.event.issue.html_url || github.event.pull_request.html_url }} \n Synced by Github Actions, tagged by ${{ github.actor }}"
+ # customfield_10091 is Team (R&D)
+ fields: '{"customfield_10091": ["TF-DevEx"], "labels": ["Github"]}'
+
diff --git a/v0.10.0/.github/workflows/test.yml b/v0.10.0/.github/workflows/test.yml
new file mode 100644
index 0000000..532b353
--- /dev/null
+++ b/v0.10.0/.github/workflows/test.yml
@@ -0,0 +1,80 @@
+name: Test
+
+on:
+ pull_request:
+ branches: [ main ]
+ paths-ignore:
+ - 'README.md'
+ - 'CHANGELOG.md'
+ - 'website/*'
+ push:
+ branches: [ main ]
+ paths-ignore:
+ - 'README.md'
+ - 'CHANGELOG.md'
+ - 'website/*'
+
+jobs:
+
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ timeout-minutes: 5
+
+ strategy:
+ matrix:
+ go-version: [ '1.20', '1.21' ]
+
+ steps:
+
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
+ with:
+ go-version: ${{ matrix.go-version }}
+
+ - name: Run linters
+ uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0
+ with:
+ version: latest
+
+ - name: Generate
+ run: make generate
+
+ - name: Confirm no diff
+ run: |
+ git diff --compact-summary --exit-code || \
+ (echo "*** Unexpected differences after code generation. Run 'make generate' and commit."; exit 1)
+
+ - name: Build
+ run: make build
+
+ test:
+ name: 'Acc. Tests (OS: ${{ matrix.os }} / TF: ${{ matrix.terraform }})'
+ needs: build
+ runs-on: ${{ matrix.os }}
+ timeout-minutes: 15
+
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+ - macos-latest
+ - windows-latest
+ - ubuntu-latest
+ terraform: ${{ fromJSON(vars.TF_VERSIONS_PROTOCOL_V5) }}
+
+ steps:
+
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
+ with:
+ go-version-file: 'go.mod'
+
+ - name: Setup Terraform ${{ matrix.terraform }}
+ uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2.0.3
+ with:
+ terraform_version: ${{ matrix.terraform }}.*
+ terraform_wrapper: false
+
+ - name: Run acceptance test
+ run: make testacc
diff --git a/v0.10.0/.gitignore b/v0.10.0/.gitignore
new file mode 100644
index 0000000..ebe6081
--- /dev/null
+++ b/v0.10.0/.gitignore
@@ -0,0 +1,6 @@
+*~
+.*.swp
+.idea
+.vscode
+dist/
+terraform-provider-time
diff --git a/v0.10.0/.golangci.yml b/v0.10.0/.golangci.yml
new file mode 100644
index 0000000..716733a
--- /dev/null
+++ b/v0.10.0/.golangci.yml
@@ -0,0 +1,30 @@
+
+issues:
+ max-per-linter: 0
+ max-same-issues: 0
+
+linters:
+ disable-all: true
+ enable:
+ - durationcheck
+ - errcheck
+ - exportloopref
+ - forcetypeassert
+ - godot
+ - gofmt
+ - gosimple
+ - ineffassign
+ - makezero
+ - misspell
+ - nilerr
+ - predeclared
+ - staticcheck
+ - tenv
+ - unconvert
+ - unparam
+ - unused
+ - vet
+
+run:
+ # Prevent false positive timeouts in CI
+ timeout: 5m
diff --git a/v0.10.0/.goreleaser.yml b/v0.10.0/.goreleaser.yml
new file mode 100644
index 0000000..90b209d
--- /dev/null
+++ b/v0.10.0/.goreleaser.yml
@@ -0,0 +1,77 @@
+archives:
+ - files:
+ # Ensure only built binary is archived
+ - 'none*'
+ format: zip
+ name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}'
+before:
+ hooks:
+ - 'go mod download'
+builds:
+ - # Binary naming only required for Terraform CLI 0.12
+ binary: '{{ .ProjectName }}_v{{ .Version }}_x5'
+ env:
+ - CGO_ENABLED=0
+ flags:
+ - -trimpath
+ goos:
+ - darwin
+ - freebsd
+ - linux
+ - windows
+ goarch:
+ - '386'
+ - amd64
+ - arm
+ - arm64
+ ignore:
+ - goarch: arm
+ goos: windows
+ - goarch: arm64
+ goos: freebsd
+ - goarch: arm64
+ goos: windows
+ ldflags:
+ - -s -w -X main.Version={{.Version}}
+ mod_timestamp: '{{ .CommitTimestamp }}'
+checksum:
+ algorithm: sha256
+ extra_files:
+ - glob: 'terraform-registry-manifest.json'
+ name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
+ name_template: '{{ .ProjectName }}_{{ .Version }}_SHA256SUMS'
+milestones:
+ - close: true
+publishers:
+ - checksum: true
+ # Terraform CLI 0.10 - 0.11 perform discovery via HTTP headers on releases.hashicorp.com
+ # For providers which have existed since those CLI versions, exclude
+ # discovery by setting the protocol version headers to 5.
+ cmd: |
+ hc-releases upload -product {{ .ProjectName }} -version {{ .Version }} -file={{ .ArtifactPath }}={{ .ArtifactName }} -header=x-terraform-protocol-version=5 -header=x-terraform-protocol-versions=5.0
+ env:
+ - HC_RELEASES_HOST={{ .Env.HC_RELEASES_HOST }}
+ - HC_RELEASES_KEY={{ .Env.HC_RELEASES_KEY }}
+ extra_files:
+ - glob: 'terraform-registry-manifest.json'
+ name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
+ name: upload
+ signature: true
+release:
+ extra_files:
+ - glob: 'terraform-registry-manifest.json'
+ name_template: '{{ .ProjectName }}_{{ .Version }}_manifest.json'
+ ids:
+ - none
+signs:
+ - args: ["sign", "--dearmor", "--file", "${artifact}", "--out", "${signature}"]
+ artifacts: checksum
+ cmd: signore
+ signature: ${artifact}.sig
+ - args: ["sign", "--dearmor", "--file", "${artifact}", "--out", "${signature}"]
+ artifacts: checksum
+ cmd: signore
+ id: key-id
+ signature: ${artifact}.72D7468F.sig
+snapshot:
+ name_template: "{{ .Tag }}-next"
diff --git a/v0.10.0/.release/release-metadata.hcl b/v0.10.0/.release/release-metadata.hcl
new file mode 100644
index 0000000..9348ac2
--- /dev/null
+++ b/v0.10.0/.release/release-metadata.hcl
@@ -0,0 +1,2 @@
+url_source_repository = "https://github.com/hashicorp/terraform-provider-time"
+url_license = "https://github.com/hashicorp/terraform-provider-time/blob/main/LICENSE"
diff --git a/v0.10.0/CHANGELOG.md b/v0.10.0/CHANGELOG.md
new file mode 100644
index 0000000..0105b21
--- /dev/null
+++ b/v0.10.0/CHANGELOG.md
@@ -0,0 +1,106 @@
+## 0.10.0 (December 06, 2023)
+
+BUG FIXES:
+
+* resource/time_offset: Fix bug preventing multiple offset arguments from being set ([#189](https://github.com/hashicorp/terraform-provider-time/issues/189))
+
+## 0.9.2 (November 28, 2023)
+
+NOTES:
+
+* This release introduces no functional changes. It does however include dependency updates which address upstream CVEs. ([#263](https://github.com/hashicorp/terraform-provider-time/issues/263))
+
+## 0.9.1 (November 2, 2022)
+
+BUG FIXES:
+
+* resource/time_rotating: Correctly retrieve the Terraform state during update ([#132](https://github.com/hashicorp/terraform-provider-time/pull/132))
+
+## 0.9.0 (October 11, 2022)
+
+NOTES:
+
+* provider: Rewritten to use the new [`terraform-plugin-framework`](https://www.terraform.io/plugin/framework) ([#112](https://github.com/hashicorp/terraform-provider-time/pull/112))
+
+## 0.8.0 (August 10, 2022)
+
+BUG FIXES:
+
+* documentation: Changed wording from "Conflicts with other `offset_`/`rotation_` arguments." to "At least one of the `offset_`/`rotation_` arguments must be configured." to correctly reflect the use of `AtLeastOneOf` ([#105](https://github.com/hashicorp/terraform-provider-time/pull/105))
+
+NOTES:
+
+* provider: Upgrade Go version to 1.18 ([#114](https://github.com/hashicorp/terraform-provider-time/pull/114))
+* provider: Enable `golangci-lint` ([#105](https://github.com/hashicorp/terraform-provider-time/pull/105))
+
+## 0.7.2 (July 01, 2021)
+
+BUG FIXES:
+
+* resource/time_sleep: Prevent `context deadline exceeded` error when timeout duration is configured above 20 minutes ([#45](https://github.com/hashicorp/terraform-provider-time/issues/45))
+
+## 0.7.1 (May 04, 2021)
+
+BUG FIXES:
+
+* provider: Ensure `darwin/arm64` platform is included in releases
+
+## 0.7.0 (February 19, 2021)
+
+Binary releases of this provider now include the darwin-arm64 platform. This version contains no further changes.
+
+## 0.6.0 (October 04, 2020)
+
+BREAKING CHANGES:
+
+* Dropped support for Terraform 0.11 and lower ([#16](https://github.com/hashicorp/terraform-provider-time/issues/16))
+
+ENHANCEMENTS
+
+* Made `time_sleep` context aware, allowing easier early cancellation ([#16](https://github.com/hashicorp/terraform-provider-time/issues/16))
+
+## 0.5.0 (May 13, 2020)
+
+FEATURES
+
+* **New Resource:** `time_sleep` ([#12](https://github.com/hashicorp/terraform-provider-time/issues/12))
+
+# 0.4.0 (April 21, 2020)
+
+BREAKING CHANGES:
+
+* resource/time_offset: `keepers` argument renamed to `triggers`
+* resource/time_offset: Remove non-RFC3339 RFC and `unixdate` attribute
+* resource/time_rotating: `keepers` argument renamed to `triggers`
+* resource/time_rotating: Remove non-RFC3339 RFC and `unixdate` attributes
+* resource/time_static: `keepers` argument renamed to `triggers`
+* resource/time_static: Remove non-RFC3339 RFC and `unixdate` attributes
+
+# v0.3.0
+
+ENHANCEMENTS:
+
+* resource/time_offset: Add `keepers` argument
+* resource/time_rotating: Add `keepers` argument
+* resource/time_static: Add `keepers` argument
+
+BUG FIXES:
+
+* resource/time_offset: Ensure `base_rfc3339` is always set in Terraform state during creation, even if unconfigured
+
+# v0.2.0
+
+BREAKING CHANGES:
+
+* resource/time_static: The `expiration_` arguments have been moved to the new `time_rotating` resource as `rotation_` arguments.
+
+FEATURES:
+
+* **New Resource:** `time_offset`
+* **New Resource:** `time_rotating`
+
+# v0.1.0
+
+FEATURES:
+
+* **New Resource:** `time_static`
diff --git a/v0.10.0/GNUmakefile b/v0.10.0/GNUmakefile
new file mode 100644
index 0000000..e0de862
--- /dev/null
+++ b/v0.10.0/GNUmakefile
@@ -0,0 +1,26 @@
+default: build
+
+build:
+ go build -v ./...
+
+install: build
+ go install -v ./...
+
+# See https://golangci-lint.run/
+lint:
+ golangci-lint run
+
+# Generate docs and copywrite headers
+generate:
+ cd tools; go generate ./...
+
+fmt:
+ gofmt -s -w -e .
+
+test:
+ go test -v -cover -timeout=120s -parallel=4 ./...
+
+testacc:
+ TF_ACC=1 go test -v -cover -timeout 120m ./...
+
+.PHONY: build install lint generate fmt test testacc
diff --git a/v0.10.0/LICENSE b/v0.10.0/LICENSE
new file mode 100644
index 0000000..c121cee
--- /dev/null
+++ b/v0.10.0/LICENSE
@@ -0,0 +1,375 @@
+Copyright (c) 2020 HashiCorp, Inc.
+
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/v0.10.0/README.md b/v0.10.0/README.md
new file mode 100644
index 0000000..82c6fbd
--- /dev/null
+++ b/v0.10.0/README.md
@@ -0,0 +1,137 @@
+# Terraform Provider: Time
+
+Terraform Provider for time-based resources.
+
+Please note: Issues on this repository are intended to be related to bugs or feature requests with this particular provider codebase. See [Terraform Community](https://www.terraform.io/community.html) for a list of resources to ask questions about Terraform or this provider and its usage.
+
+## Requirements
+
+* [Terraform](https://www.terraform.io/downloads)
+* [Go](https://go.dev/doc/install) (1.20)
+* [GNU Make](https://www.gnu.org/software/make/)
+* [golangci-lint](https://golangci-lint.run/usage/install/#local-installation) (optional)
+
+## Using the Provider
+
+This Terraform Provider is available to install automatically via `terraform init`. It is recommended to setup the following Terraform configuration to pin the major version:
+
+```hcl
+# Terraform 0.13 and later
+terraform {
+ required_providers {
+ time = {
+ source = "hashicorp/time"
+ version = "~> X.Y" # where X.Y is the current major version and minor version
+ }
+ }
+}
+
+# Terraform 0.12
+terraform {
+ required_providers {
+ time = "~> X.Y" # where X.Y is the current major version and minor version
+ }
+}
+```
+
+## Documentation, questions and discussions
+Official documentation on how to use this provider can be found on the
+[Terraform Registry](https://registry.terraform.io/providers/hashicorp/time/latest/docs).
+In case of specific questions or discussions, please use the
+HashiCorp [Terraform Providers Discuss forums](https://discuss.hashicorp.com/c/terraform-providers/31),
+in accordance with HashiCorp [Community Guidelines](https://www.hashicorp.com/community-guidelines).
+
+We also provide:
+
+* [Support](.github/SUPPORT.md) page for help when using the provider
+* [Contributing](.github/CONTRIBUTING.md) guidelines in case you want to help this project
+
+## Compatibility
+
+Compatibility table between this provider, the [Terraform Plugin Protocol](https://www.terraform.io/plugin/how-terraform-works#terraform-plugin-protocol)
+version it implements, and Terraform:
+
+| Time Provider | Terraform Plugin Protocol | Terraform |
+|:-------------:|:----------------------------------:|:---------:|
+| `>= 0.8.x` | `5` | `>= 0.12` |
+| `>= 0.7.x` | `5` | `>= 0.12` |
+| `>= 0.6.x` | `5` | `>= 0.12` |
+| `>= 0.5.x` | `4` and `5` | `<= 0.12` |
+| `>= 0.4.x` | `4` and `5` | `<= 0.12` |
+
+Details can be found querying the [Registry API](https://www.terraform.io/internals/provider-registry-protocol#list-available-versions)
+that return all the details about which version are currently available for a particular provider.
+[Here](https://registry.terraform.io/v1/providers/hashicorp/time/versions) are the details for Time (JSON response).
+
+## Development
+
+### Building
+
+1. `git clone` this repository and `cd` into its directory
+2. `make` will trigger the Golang build
+
+The provided `GNUmakefile` defines additional commands generally useful during development,
+like for running tests, generating documentation, code formatting and linting.
+Taking a look at it's content is recommended.
+
+### Testing
+
+In order to test the provider, you can run
+
+* `make test` to run provider tests
+* `make testacc` to run provider acceptance tests
+
+It's important to note that acceptance tests (`testacc`) will actually spawn
+`terraform` and the provider. Read more about they work on the
+[official page](https://www.terraform.io/plugin/sdkv2/testing/acceptance-tests).
+
+### Generating documentation
+
+This provider uses [terraform-plugin-docs](https://github.com/hashicorp/terraform-plugin-docs/)
+to generate documentation and store it in the `docs/` directory.
+Once a release is cut, the Terraform Registry will download the documentation from `docs/`
+and associate it with the release version. Read more about how this works on the
+[official page](https://www.terraform.io/registry/providers/docs).
+
+Use `make generate` to ensure the documentation is regenerated with any changes.
+
+### Using a development build
+
+If [running tests and acceptance tests](#testing) isn't enough, it's possible to set up a local terraform configuration
+to use a development builds of the provider. This can be achieved by leveraging the Terraform CLI
+[configuration file development overrides](https://www.terraform.io/cli/config/config-file#development-overrides-for-provider-developers).
+
+First, use `make install` to place a fresh development build of the provider in your
+[`${GOBIN}`](https://pkg.go.dev/cmd/go#hdr-Compile_and_install_packages_and_dependencies)
+(defaults to `${GOPATH}/bin` or `${HOME}/go/bin` if `${GOPATH}` is not set). Repeat
+this every time you make changes to the provider locally.
+
+Then, setup your environment following [these instructions](https://www.terraform.io/plugin/debugging#terraform-cli-development-overrides)
+to make your local terraform use your local build.
+
+### Testing GitHub Actions
+
+This project uses [GitHub Actions](https://docs.github.com/en/actions/automating-builds-and-tests) to realize its CI.
+
+Sometimes it might be helpful to locally reproduce the behaviour of those actions,
+and for this we use [act](https://github.com/nektos/act). Once installed, you can _simulate_ the actions executed
+when opening a PR with:
+
+```shell
+# List of workflows for the 'pull_request' action
+$ act -l pull_request
+
+# Execute the workflows associated with the `pull_request' action
+$ act pull_request
+```
+
+## Releasing
+
+The release process is automated via GitHub Actions, and it's defined in the Workflow
+[release.yml](./.github/workflows/release.yml).
+
+Each release is cut by pushing a [semantically versioned](https://semver.org/) tag to the default branch.
+
+## License
+
+[Mozilla Public License v2.0](./LICENSE)
diff --git a/v0.10.0/docs/cdktf/python/index.md b/v0.10.0/docs/cdktf/python/index.md
new file mode 100644
index 0000000..4b0bde4
--- /dev/null
+++ b/v0.10.0/docs/cdktf/python/index.md
@@ -0,0 +1,57 @@
+---
+page_title: "Provider: Time"
+description: |-
+ The time provider is used to interact with time-based resources.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# Time Provider
+
+The time provider is used to interact with time-based resources. The provider itself has no configuration options.
+
+Use the navigation to the left to read about the available resources.
+
+## Resource "Triggers"
+
+Certain time resources, only perform actions during specific lifecycle actions:
+
+- `time_offset`: Saves base timestamp into Terraform state only when created.
+- `time_sleep`: Sleeps when created and/or destroyed.
+- `time_static`: Saves base timestamp into Terraform state only when created.
+
+These resources provide an optional map argument called `triggers` that can be populated with arbitrary key/value pairs. When the keys or values of this argument are updated, Terraform will re-perform the desired action, such as updating the base timestamp or sleeping again.
+
+For example:
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import Token, Fn, TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.aws.instance import Instance
+from imports.time.static_resource import StaticResource
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ ami_update = StaticResource(self, "ami_update",
+ triggers={
+ "ami_id": Token.as_string(example.id)
+ }
+ )
+ Instance(self, "server",
+ ami=Token.as_string(Fn.lookup_nested(ami_update, ["triggers", "ami_id"])),
+ tags={
+ "AmiUpdateTime": ami_update.rfc3339
+ }
+ )
+```
+
+`triggers` are *not* treated as sensitive attributes; a value used for `triggers` will be displayed in Terraform UI output as plaintext.
+
+To force a these actions to reoccur without updating `triggers`, the [`terraform taint` command](https://www.terraform.io/docs/commands/taint.html) can be used to produce the action on the next run.
+
+<!-- cache-key: cdktf-0.19.0 input-bc12960a9acfa8c6ebb6834f5fc7a95b4cc9baf2b76cbb71ea47c692591f4c4f 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/python/resources/offset.md b/v0.10.0/docs/cdktf/python/resources/offset.md
new file mode 100644
index 0000000..437f050
--- /dev/null
+++ b/v0.10.0/docs/cdktf/python/resources/offset.md
@@ -0,0 +1,127 @@
+---
+page_title: "time_offset Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages an offset time resource, which keeps an UTC timestamp stored in the Terraform state that is offset from a locally sourced base timestamp. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# time_offset (Resource)
+
+Manages an offset time resource, which keeps an UTC timestamp stored in the Terraform state that is offset from a locally sourced base timestamp. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html).
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import TerraformOutput, TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.time.offset import Offset
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ example = Offset(self, "example",
+ offset_days=7
+ )
+ TerraformOutput(self, "one_week_from_now",
+ value=example.rfc3339
+ )
+```
+
+### Multiple Offsets Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import TerraformOutput, TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.time.offset import Offset
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ example = Offset(self, "example",
+ offset_months=1,
+ offset_years=1
+ )
+ TerraformOutput(self, "one_year_and_month_from_now",
+ value=example.rfc3339
+ )
+```
+
+### Triggers Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import Token, Fn, TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.aws.instance import Instance
+from imports.time.offset import Offset
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ ami_update = Offset(self, "ami_update",
+ offset_days=7,
+ triggers={
+ "ami_id": Token.as_string(example.id)
+ }
+ )
+ Instance(self, "server",
+ ami=Token.as_string(Fn.lookup_nested(ami_update, ["triggers", "ami_id"])),
+ tags={
+ "ExpirationTime": ami_update.rfc3339
+ }
+ )
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `base_rfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `offset_days` (Number) Number of days to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_hours` (Number) Number of hours to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_minutes` (Number) Number of minutes to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_months` (Number) Number of months to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_seconds` (Number) Number of seconds to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_years` (Number) Number of years to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of offset timestamp.
+- `hour` (Number) Number hour of offset timestamp.
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of offset timestamp.
+- `month` (Number) Number month of offset timestamp.
+- `rfc3339` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `second` (Number) Number second of offset timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of offset timestamp.
+
+## Import
+
+This resource can be imported using the base UTC RFC3339 timestamp and offset years, months, days, hours, minutes, and seconds, separated by commas (`,`), e.g.
+
+```shell
+terraform import time_offset.example 2020-02-12T06:36:13Z,0,0,7,0,0,0
+```
+
+The `triggers` argument cannot be imported.
+<!-- cache-key: cdktf-0.19.0 input-9c8ec1841600576ce1daecf6956fcc4e4e5ad75d031b09cbbc4a784278fcf793 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/python/resources/rotating.md b/v0.10.0/docs/cdktf/python/resources/rotating.md
new file mode 100644
index 0000000..1a2adb4
--- /dev/null
+++ b/v0.10.0/docs/cdktf/python/resources/rotating.md
@@ -0,0 +1,78 @@
+---
+page_title: "time_rotating Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a rotating time resource, which keeps a rotating UTC timestamp stored in the Terraform state and proposes resource recreation when the locally sourced current time is beyond the rotation time. This rotation only occurs when Terraform is executed, meaning there will be drift between the rotation timestamp and actual rotation. The new rotation timestamp offset includes this drift. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html by only forcing a new value on the set cadence.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# time_rotating (Resource)
+
+Manages a rotating time resource, which keeps a rotating UTC timestamp stored in the Terraform state and proposes resource recreation when the locally sourced current time is beyond the rotation time. This rotation only occurs when Terraform is executed, meaning there will be drift between the rotation timestamp and actual rotation. The new rotation timestamp offset includes this drift. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html) by only forcing a new value on the set cadence.
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.time.rotating import Rotating
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ Rotating(self, "example",
+ rotation_days=30
+ )
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `rfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `rotation_days` (Number) Number of days to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_hours` (Number) Number of hours to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_minutes` (Number) Number of minutes to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_months` (Number) Number of months to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_rfc3339` (String) Configure the rotation timestamp with an [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format of the offset timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_years` (Number) Number of years to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. These conditions recreate the resource in addition to other rotation arguments. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of timestamp.
+- `hour` (Number) Number hour of timestamp.
+- `id` (String) RFC3339 format of the timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of timestamp.
+- `month` (Number) Number month of timestamp.
+- `second` (Number) Number second of timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of timestamp.
+
+## Import
+
+This resource can be imported using the base UTC RFC3339 value and rotation years, months, days, hours, and minutes, separated by commas (`,`), e.g. for 30 days
+
+```shell
+terraform import time_rotating.example 2020-02-12T06:36:13Z,0,0,30,0,0
+```
+
+Otherwise, to import with the rotation RFC3339 value, the base UTC RFC3339 value and rotation UTC RFC3339 value, separated by commas (`,`), e.g.
+
+```shell
+terraform import time_rotating.example 2020-02-12T06:36:13Z,2020-02-13T06:36:13Z
+```
+
+The `triggers` argument cannot be imported.
+
+<!-- cache-key: cdktf-0.19.0 input-eec8d2abb9e41d257337f27d082bf8b4b5627f1c470562afec7afd5ff5053b6b 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/python/resources/sleep.md b/v0.10.0/docs/cdktf/python/resources/sleep.md
new file mode 100644
index 0000000..ce50cd2
--- /dev/null
+++ b/v0.10.0/docs/cdktf/python/resources/sleep.md
@@ -0,0 +1,140 @@
+---
+page_title: "time_sleep Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a resource that delays creation and/or destruction, typically for further resources. This prevents cross-platform compatibility and destroy-time issues with using the local-exec provisioner https://www.terraform.io/docs/provisioners/local-exec.html.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# time_sleep (Resource)
+
+Manages a resource that delays creation and/or destruction, typically for further resources. This prevents cross-platform compatibility and destroy-time issues with using the [`local-exec` provisioner](https://www.terraform.io/docs/provisioners/local-exec.html).
+
+-> In many cases, this resource should be considered a workaround for issues that should be reported and handled in downstream Terraform Provider logic. Downstream resources can usually introduce or adjust retries in their code to handle time delay issues for all Terraform configurations or upstream resources can be improved to better wait for a resource to be fully ready and available.
+
+## Example Usage
+
+### Delay Create Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.null.resource import Resource
+from imports.time.sleep import Sleep
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ # The following providers are missing schema information and might need manual adjustments to synthesize correctly: null.
+ # For a more precise conversion please use the --provider flag in convert.
+ null_resource_previous = Resource(self, "previous")
+ wait30_seconds = Sleep(self, "wait_30_seconds",
+ create_duration="30s",
+ depends_on=[null_resource_previous]
+ )
+ Resource(self, "next",
+ depends_on=[wait30_seconds]
+ )
+```
+
+### Delay Destroy Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.null.resource import Resource
+from imports.time.sleep import Sleep
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ # The following providers are missing schema information and might need manual adjustments to synthesize correctly: null.
+ # For a more precise conversion please use the --provider flag in convert.
+ null_resource_previous = Resource(self, "previous")
+ wait30_seconds = Sleep(self, "wait_30_seconds",
+ depends_on=[null_resource_previous],
+ destroy_duration="30s"
+ )
+ Resource(self, "next",
+ depends_on=[wait30_seconds]
+ )
+```
+
+### Triggers Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import Token, Fn, TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.aws.db_subnet_group import DbSubnetGroup
+from imports.aws.ram_resource_association import RamResourceAssociation
+from imports.time.sleep import Sleep
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ example = RamResourceAssociation(self, "example",
+ resource_arn=Token.as_string(aws_subnet_example.arn),
+ resource_share_arn=Token.as_string(aws_ram_resource_share_example.arn)
+ )
+ ram_resource_propagation = Sleep(self, "ram_resource_propagation",
+ create_duration="60s",
+ triggers={
+ "subnet_arn": example.resource_arn,
+ "subnet_id": Token.as_string(aws_subnet_example.id)
+ }
+ )
+ aws_db_subnet_group_example = DbSubnetGroup(self, "example_2",
+ name="example",
+ subnet_ids=[
+ Token.as_string(
+ Fn.lookup_nested(ram_resource_propagation.triggers, ["\"subnet_id\""]))
+ ]
+ )
+ # This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.
+ aws_db_subnet_group_example.override_logical_id("example")
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `create_duration` (String) [Time duration](https://golang.org/pkg/time/#ParseDuration) to delay resource creation. For example, `30s` for 30 seconds or `5m` for 5 minutes. Updating this value by itself will not trigger a delay.
+- `destroy_duration` (String) [Time duration](https://golang.org/pkg/time/#ParseDuration) to delay resource destroy. For example, `30s` for 30 seconds or `5m` for 5 minutes. Updating this value by itself will not trigger a delay. This value or any updates to it must be successfully applied into the Terraform state before destroying this resource to take effect.
+- `triggers` (Map of String) (Optional) Arbitrary map of values that, when changed, will run any creation or destroy delays again. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+
+## Import
+
+This resource can be imported with the `create_duration` and `destroy_duration`, separated by a comma (`,`).
+
+e.g. For 30 seconds create duration with no destroy duration:
+
+```shell
+terraform import time_sleep.example 30s,
+```
+
+e.g. For 30 seconds destroy duration with no create duration:
+
+```shell
+terraform import time_sleep.example ,30s
+```
+
+The `triggers` argument cannot be imported.
+<!-- cache-key: cdktf-0.19.0 input-73a2d0d8f07a92177ff8e69d3b8b07c852fc6f16cd4c3f99105c5d12d1cda96c 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/python/resources/static.md b/v0.10.0/docs/cdktf/python/resources/static.md
new file mode 100644
index 0000000..04bdcce
--- /dev/null
+++ b/v0.10.0/docs/cdktf/python/resources/static.md
@@ -0,0 +1,95 @@
+---
+page_title: "time_static Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a static time resource, which keeps a locally sourced UTC timestamp stored in the Terraform state. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# time_static (Resource)
+
+Manages a static time resource, which keeps a locally sourced UTC timestamp stored in the Terraform state. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html).
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import TerraformOutput, TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.time.static_resource import StaticResource
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ example = StaticResource(self, "example")
+ TerraformOutput(self, "current_time",
+ value=example.rfc3339
+ )
+```
+
+### Triggers Usage
+
+```python
+# DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+from constructs import Construct
+from cdktf import Token, Fn, TerraformStack
+#
+# Provider bindings are generated by running `cdktf get`.
+# See https://cdk.tf/provider-generation for more details.
+#
+from imports.aws.instance import Instance
+from imports.time.static_resource import StaticResource
+class MyConvertedCode(TerraformStack):
+ def __init__(self, scope, name):
+ super().__init__(scope, name)
+ ami_update = StaticResource(self, "ami_update",
+ triggers={
+ "ami_id": Token.as_string(example.id)
+ }
+ )
+ Instance(self, "server",
+ ami=Token.as_string(Fn.lookup_nested(ami_update, ["triggers", "ami_id"])),
+ tags={
+ "AmiUpdateTime": ami_update.rfc3339
+ }
+ )
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `rfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of timestamp.
+- `hour` (Number) Number hour of timestamp.
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of timestamp.
+- `month` (Number) Number month of timestamp.
+- `second` (Number) Number second of timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of timestamp.
+
+
+## Import
+
+This resource can be imported using the UTC RFC3339 value, e.g.
+
+```shell
+terraform import time_static.example 2020-02-12T06:36:13Z
+```
+
+The `triggers` argument cannot be imported.
+<!-- cache-key: cdktf-0.19.0 input-2146f927c8bb8e527bb2f114b61e2f9275e5bb5fe013e14866a96eaf7e90c011 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/typescript/index.md b/v0.10.0/docs/cdktf/typescript/index.md
new file mode 100644
index 0000000..b24c1c0
--- /dev/null
+++ b/v0.10.0/docs/cdktf/typescript/index.md
@@ -0,0 +1,60 @@
+---
+page_title: "Provider: Time"
+description: |-
+ The time provider is used to interact with time-based resources.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# Time Provider
+
+The time provider is used to interact with time-based resources. The provider itself has no configuration options.
+
+Use the navigation to the left to read about the available resources.
+
+## Resource "Triggers"
+
+Certain time resources, only perform actions during specific lifecycle actions:
+
+- `timeOffset`: Saves base timestamp into Terraform state only when created.
+- `timeSleep`: Sleeps when created and/or destroyed.
+- `timeStatic`: Saves base timestamp into Terraform state only when created.
+
+These resources provide an optional map argument called `triggers` that can be populated with arbitrary key/value pairs. When the keys or values of this argument are updated, Terraform will re-perform the desired action, such as updating the base timestamp or sleeping again.
+
+For example:
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { Token, Fn, TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { Instance } from "./.gen/providers/aws/instance";
+import { StaticResource } from "./.gen/providers/time/static-resource";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ const amiUpdate = new StaticResource(this, "ami_update", {
+ triggers: {
+ ami_id: Token.asString(example.id),
+ },
+ });
+ new Instance(this, "server", {
+ ami: Token.asString(Fn.lookupNested(amiUpdate, ["triggers", "ami_id"])),
+ tags: {
+ AmiUpdateTime: amiUpdate.rfc3339,
+ },
+ });
+ }
+}
+
+```
+
+`triggers` are *not* treated as sensitive attributes; a value used for `triggers` will be displayed in Terraform UI output as plaintext.
+
+To force a these actions to reoccur without updating `triggers`, the [`terraform taint` command](https://www.terraform.io/docs/commands/taint.html) can be used to produce the action on the next run.
+
+<!-- cache-key: cdktf-0.19.0 input-bc12960a9acfa8c6ebb6834f5fc7a95b4cc9baf2b76cbb71ea47c692591f4c4f 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/typescript/resources/offset.md b/v0.10.0/docs/cdktf/typescript/resources/offset.md
new file mode 100644
index 0000000..694f33d
--- /dev/null
+++ b/v0.10.0/docs/cdktf/typescript/resources/offset.md
@@ -0,0 +1,136 @@
+---
+page_title: "time_offset Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages an offset time resource, which keeps an UTC timestamp stored in the Terraform state that is offset from a locally sourced base timestamp. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# time_offset (Resource)
+
+Manages an offset time resource, which keeps an UTC timestamp stored in the Terraform state that is offset from a locally sourced base timestamp. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html).
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { TerraformOutput, TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { Offset } from "./.gen/providers/time/offset";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ const example = new Offset(this, "example", {
+ offsetDays: 7,
+ });
+ new TerraformOutput(this, "one_week_from_now", {
+ value: example.rfc3339,
+ });
+ }
+}
+
+```
+
+### Multiple Offsets Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { TerraformOutput, TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { Offset } from "./.gen/providers/time/offset";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ const example = new Offset(this, "example", {
+ offsetMonths: 1,
+ offsetYears: 1,
+ });
+ new TerraformOutput(this, "one_year_and_month_from_now", {
+ value: example.rfc3339,
+ });
+ }
+}
+
+```
+
+### Triggers Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { Token, Fn, TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { Instance } from "./.gen/providers/aws/instance";
+import { Offset } from "./.gen/providers/time/offset";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ const amiUpdate = new Offset(this, "ami_update", {
+ offsetDays: 7,
+ triggers: {
+ ami_id: Token.asString(example.id),
+ },
+ });
+ new Instance(this, "server", {
+ ami: Token.asString(Fn.lookupNested(amiUpdate, ["triggers", "ami_id"])),
+ tags: {
+ ExpirationTime: amiUpdate.rfc3339,
+ },
+ });
+ }
+}
+
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `baseRfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `offsetDays` (Number) Number of days to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offsetHours` (Number) Number of hours to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offsetMinutes` (Number) Number of minutes to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offsetMonths` (Number) Number of months to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offsetSeconds` (Number) Number of seconds to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offsetYears` (Number) Number of years to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of offset timestamp.
+- `hour` (Number) Number hour of offset timestamp.
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of offset timestamp.
+- `month` (Number) Number month of offset timestamp.
+- `rfc3339` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `second` (Number) Number second of offset timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of offset timestamp.
+
+## Import
+
+This resource can be imported using the base UTC RFC3339 timestamp and offset years, months, days, hours, minutes, and seconds, separated by commas (`,`), e.g.
+
+```shell
+terraform import time_offset.example 2020-02-12T06:36:13Z,0,0,7,0,0,0
+```
+
+The `triggers` argument cannot be imported.
+<!-- cache-key: cdktf-0.19.0 input-9c8ec1841600576ce1daecf6956fcc4e4e5ad75d031b09cbbc4a784278fcf793 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/typescript/resources/rotating.md b/v0.10.0/docs/cdktf/typescript/resources/rotating.md
new file mode 100644
index 0000000..73bcf66
--- /dev/null
+++ b/v0.10.0/docs/cdktf/typescript/resources/rotating.md
@@ -0,0 +1,81 @@
+---
+page_title: "time_rotating Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a rotating time resource, which keeps a rotating UTC timestamp stored in the Terraform state and proposes resource recreation when the locally sourced current time is beyond the rotation time. This rotation only occurs when Terraform is executed, meaning there will be drift between the rotation timestamp and actual rotation. The new rotation timestamp offset includes this drift. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html by only forcing a new value on the set cadence.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# time_rotating (Resource)
+
+Manages a rotating time resource, which keeps a rotating UTC timestamp stored in the Terraform state and proposes resource recreation when the locally sourced current time is beyond the rotation time. This rotation only occurs when Terraform is executed, meaning there will be drift between the rotation timestamp and actual rotation. The new rotation timestamp offset includes this drift. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html) by only forcing a new value on the set cadence.
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { Rotating } from "./.gen/providers/time/rotating";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ new Rotating(this, "example", {
+ rotationDays: 30,
+ });
+ }
+}
+
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `rfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `rotationDays` (Number) Number of days to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotationHours` (Number) Number of hours to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotationMinutes` (Number) Number of minutes to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotationMonths` (Number) Number of months to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotationRfc3339` (String) Configure the rotation timestamp with an [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format of the offset timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotationYears` (Number) Number of years to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. These conditions recreate the resource in addition to other rotation arguments. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of timestamp.
+- `hour` (Number) Number hour of timestamp.
+- `id` (String) RFC3339 format of the timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of timestamp.
+- `month` (Number) Number month of timestamp.
+- `second` (Number) Number second of timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of timestamp.
+
+## Import
+
+This resource can be imported using the base UTC RFC3339 value and rotation years, months, days, hours, and minutes, separated by commas (`,`), e.g. for 30 days
+
+```shell
+terraform import time_rotating.example 2020-02-12T06:36:13Z,0,0,30,0,0
+```
+
+Otherwise, to import with the rotation RFC3339 value, the base UTC RFC3339 value and rotation UTC RFC3339 value, separated by commas (`,`), e.g.
+
+```shell
+terraform import time_rotating.example 2020-02-12T06:36:13Z,2020-02-13T06:36:13Z
+```
+
+The `triggers` argument cannot be imported.
+
+<!-- cache-key: cdktf-0.19.0 input-eec8d2abb9e41d257337f27d082bf8b4b5627f1c470562afec7afd5ff5053b6b 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/typescript/resources/sleep.md b/v0.10.0/docs/cdktf/typescript/resources/sleep.md
new file mode 100644
index 0000000..1d16b78
--- /dev/null
+++ b/v0.10.0/docs/cdktf/typescript/resources/sleep.md
@@ -0,0 +1,150 @@
+---
+page_title: "time_sleep Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a resource that delays creation and/or destruction, typically for further resources. This prevents cross-platform compatibility and destroy-time issues with using the local-exec provisioner https://www.terraform.io/docs/provisioners/local-exec.html.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# time_sleep (Resource)
+
+Manages a resource that delays creation and/or destruction, typically for further resources. This prevents cross-platform compatibility and destroy-time issues with using the [`localExec` provisioner](https://www.terraform.io/docs/provisioners/local-exec.html).
+
+-> In many cases, this resource should be considered a workaround for issues that should be reported and handled in downstream Terraform Provider logic. Downstream resources can usually introduce or adjust retries in their code to handle time delay issues for all Terraform configurations or upstream resources can be improved to better wait for a resource to be fully ready and available.
+
+## Example Usage
+
+### Delay Create Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { Resource } from "./.gen/providers/null/resource";
+import { Sleep } from "./.gen/providers/time/sleep";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ /*The following providers are missing schema information and might need manual adjustments to synthesize correctly: null.
+ For a more precise conversion please use the --provider flag in convert.*/
+ const nullResourcePrevious = new Resource(this, "previous", {});
+ const wait30Seconds = new Sleep(this, "wait_30_seconds", {
+ createDuration: "30s",
+ dependsOn: [nullResourcePrevious],
+ });
+ new Resource(this, "next", {
+ dependsOn: [wait30Seconds],
+ });
+ }
+}
+
+```
+
+### Delay Destroy Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { Resource } from "./.gen/providers/null/resource";
+import { Sleep } from "./.gen/providers/time/sleep";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ /*The following providers are missing schema information and might need manual adjustments to synthesize correctly: null.
+ For a more precise conversion please use the --provider flag in convert.*/
+ const nullResourcePrevious = new Resource(this, "previous", {});
+ const wait30Seconds = new Sleep(this, "wait_30_seconds", {
+ dependsOn: [nullResourcePrevious],
+ destroyDuration: "30s",
+ });
+ new Resource(this, "next", {
+ dependsOn: [wait30Seconds],
+ });
+ }
+}
+
+```
+
+### Triggers Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { Token, Fn, TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { DbSubnetGroup } from "./.gen/providers/aws/db-subnet-group";
+import { RamResourceAssociation } from "./.gen/providers/aws/ram-resource-association";
+import { Sleep } from "./.gen/providers/time/sleep";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ const example = new RamResourceAssociation(this, "example", {
+ resourceArn: Token.asString(awsSubnetExample.arn),
+ resourceShareArn: Token.asString(awsRamResourceShareExample.arn),
+ });
+ const ramResourcePropagation = new Sleep(this, "ram_resource_propagation", {
+ createDuration: "60s",
+ triggers: {
+ subnet_arn: example.resourceArn,
+ subnet_id: Token.asString(awsSubnetExample.id),
+ },
+ });
+ const awsDbSubnetGroupExample = new DbSubnetGroup(this, "example_2", {
+ name: "example",
+ subnetIds: [
+ Token.asString(
+ Fn.lookupNested(ramResourcePropagation.triggers, ['"subnet_id"'])
+ ),
+ ],
+ });
+ /*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
+ awsDbSubnetGroupExample.overrideLogicalId("example");
+ }
+}
+
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `createDuration` (String) [Time duration](https://golang.org/pkg/time/#ParseDuration) to delay resource creation. For example, `30s` for 30 seconds or `5m` for 5 minutes. Updating this value by itself will not trigger a delay.
+- `destroyDuration` (String) [Time duration](https://golang.org/pkg/time/#ParseDuration) to delay resource destroy. For example, `30s` for 30 seconds or `5m` for 5 minutes. Updating this value by itself will not trigger a delay. This value or any updates to it must be successfully applied into the Terraform state before destroying this resource to take effect.
+- `triggers` (Map of String) (Optional) Arbitrary map of values that, when changed, will run any creation or destroy delays again. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+
+## Import
+
+This resource can be imported with the `createDuration` and `destroyDuration`, separated by a comma (`,`).
+
+e.g. For 30 seconds create duration with no destroy duration:
+
+```shell
+terraform import time_sleep.example 30s,
+```
+
+e.g. For 30 seconds destroy duration with no create duration:
+
+```shell
+terraform import time_sleep.example ,30s
+```
+
+The `triggers` argument cannot be imported.
+<!-- cache-key: cdktf-0.19.0 input-73a2d0d8f07a92177ff8e69d3b8b07c852fc6f16cd4c3f99105c5d12d1cda96c 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/cdktf/typescript/resources/static.md b/v0.10.0/docs/cdktf/typescript/resources/static.md
new file mode 100644
index 0000000..ef1163c
--- /dev/null
+++ b/v0.10.0/docs/cdktf/typescript/resources/static.md
@@ -0,0 +1,101 @@
+---
+page_title: "time_static Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a static time resource, which keeps a locally sourced UTC timestamp stored in the Terraform state. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html.
+---
+
+
+<!-- Please do not edit this file, it is generated. -->
+# time_static (Resource)
+
+Manages a static time resource, which keeps a locally sourced UTC timestamp stored in the Terraform state. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html).
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { TerraformOutput, TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { StaticResource } from "./.gen/providers/time/static-resource";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ const example = new StaticResource(this, "example", {});
+ new TerraformOutput(this, "current_time", {
+ value: example.rfc3339,
+ });
+ }
+}
+
+```
+
+### Triggers Usage
+
+```typescript
+// DO NOT EDIT. Code generated by 'cdktf convert' - Please report bugs at https://cdk.tf/bug
+import { Construct } from "constructs";
+import { Token, Fn, TerraformStack } from "cdktf";
+/*
+ * Provider bindings are generated by running `cdktf get`.
+ * See https://cdk.tf/provider-generation for more details.
+ */
+import { Instance } from "./.gen/providers/aws/instance";
+import { StaticResource } from "./.gen/providers/time/static-resource";
+class MyConvertedCode extends TerraformStack {
+ constructor(scope: Construct, name: string) {
+ super(scope, name);
+ const amiUpdate = new StaticResource(this, "ami_update", {
+ triggers: {
+ ami_id: Token.asString(example.id),
+ },
+ });
+ new Instance(this, "server", {
+ ami: Token.asString(Fn.lookupNested(amiUpdate, ["triggers", "ami_id"])),
+ tags: {
+ AmiUpdateTime: amiUpdate.rfc3339,
+ },
+ });
+ }
+}
+
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `rfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of timestamp.
+- `hour` (Number) Number hour of timestamp.
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of timestamp.
+- `month` (Number) Number month of timestamp.
+- `second` (Number) Number second of timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of timestamp.
+
+
+## Import
+
+This resource can be imported using the UTC RFC3339 value, e.g.
+
+```shell
+terraform import time_static.example 2020-02-12T06:36:13Z
+```
+
+The `triggers` argument cannot be imported.
+<!-- cache-key: cdktf-0.19.0 input-2146f927c8bb8e527bb2f114b61e2f9275e5bb5fe013e14866a96eaf7e90c011 556251879b8ed0dc4c87a76b568667e0ab5e2c46efdd14a05c556daf05678783-->
\ No newline at end of file
diff --git a/v0.10.0/docs/index.md b/v0.10.0/docs/index.md
new file mode 100644
index 0000000..5e2bcd3
--- /dev/null
+++ b/v0.10.0/docs/index.md
@@ -0,0 +1,48 @@
+---
+page_title: "Provider: Time"
+description: |-
+ The time provider is used to interact with time-based resources.
+---
+
+# Time Provider
+
+The time provider is used to interact with time-based resources. The provider itself has no configuration options.
+
+Use the navigation to the left to read about the available resources.
+
+## Resource "Triggers"
+
+Certain time resources, only perform actions during specific lifecycle actions:
+
+- `time_offset`: Saves base timestamp into Terraform state only when created.
+- `time_sleep`: Sleeps when created and/or destroyed.
+- `time_static`: Saves base timestamp into Terraform state only when created.
+
+These resources provide an optional map argument called `triggers` that can be populated with arbitrary key/value pairs. When the keys or values of this argument are updated, Terraform will re-perform the desired action, such as updating the base timestamp or sleeping again.
+
+For example:
+
+```terraform
+resource "time_static" "ami_update" {
+ triggers = {
+ # Save the time each switch of an AMI id
+ ami_id = data.aws_ami.example.id
+ }
+}
+
+resource "aws_instance" "server" {
+ # Read the AMI id "through" the time_static resource to ensure that
+ # both will change together.
+ ami = time_static.ami_update.triggers.ami_id
+
+ tags = {
+ AmiUpdateTime = time_static.ami_update.rfc3339
+ }
+
+ # ... (other aws_instance arguments) ...
+}
+```
+
+`triggers` are *not* treated as sensitive attributes; a value used for `triggers` will be displayed in Terraform UI output as plaintext.
+
+To force a these actions to reoccur without updating `triggers`, the [`terraform taint` command](https://www.terraform.io/docs/commands/taint.html) can be used to produce the action on the next run.
diff --git a/v0.10.0/docs/resources/offset.md b/v0.10.0/docs/resources/offset.md
new file mode 100644
index 0000000..05875a1
--- /dev/null
+++ b/v0.10.0/docs/resources/offset.md
@@ -0,0 +1,100 @@
+---
+page_title: "time_offset Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages an offset time resource, which keeps an UTC timestamp stored in the Terraform state that is offset from a locally sourced base timestamp. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html.
+---
+
+# time_offset (Resource)
+
+Manages an offset time resource, which keeps an UTC timestamp stored in the Terraform state that is offset from a locally sourced base timestamp. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html).
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```terraform
+resource "time_offset" "example" {
+ offset_days = 7
+}
+
+output "one_week_from_now" {
+ value = time_offset.example.rfc3339
+}
+```
+
+### Multiple Offsets Usage
+
+```terraform
+resource "time_offset" "example" {
+ offset_years = 1
+ offset_months = 1
+}
+
+output "one_year_and_month_from_now" {
+ value = time_offset.example.rfc3339
+}
+```
+
+### Triggers Usage
+
+```terraform
+resource "time_offset" "ami_update" {
+ triggers = {
+ # Save the time each switch of an AMI id
+ ami_id = data.aws_ami.example.id
+ }
+
+ offset_days = 7
+}
+
+resource "aws_instance" "server" {
+ # Read the AMI id "through" the time_offset resource to ensure that
+ # both will change together.
+ ami = time_offset.ami_update.triggers.ami_id
+
+ tags = {
+ ExpirationTime = time_offset.ami_update.rfc3339
+ }
+
+ # ... (other aws_instance arguments) ...
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `base_rfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `offset_days` (Number) Number of days to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_hours` (Number) Number of hours to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_minutes` (Number) Number of minutes to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_months` (Number) Number of months to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_seconds` (Number) Number of seconds to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `offset_years` (Number) Number of years to offset the base timestamp. At least one of the 'offset_' arguments must be configured.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of offset timestamp.
+- `hour` (Number) Number hour of offset timestamp.
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of offset timestamp.
+- `month` (Number) Number month of offset timestamp.
+- `rfc3339` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `second` (Number) Number second of offset timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of offset timestamp.
+
+## Import
+
+This resource can be imported using the base UTC RFC3339 timestamp and offset years, months, days, hours, minutes, and seconds, separated by commas (`,`), e.g.
+
+```shell
+terraform import time_offset.example 2020-02-12T06:36:13Z,0,0,7,0,0,0
+```
+
+The `triggers` argument cannot be imported.
\ No newline at end of file
diff --git a/v0.10.0/docs/resources/rotating.md b/v0.10.0/docs/resources/rotating.md
new file mode 100644
index 0000000..3fde9ba
--- /dev/null
+++ b/v0.10.0/docs/resources/rotating.md
@@ -0,0 +1,63 @@
+---
+page_title: "time_rotating Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a rotating time resource, which keeps a rotating UTC timestamp stored in the Terraform state and proposes resource recreation when the locally sourced current time is beyond the rotation time. This rotation only occurs when Terraform is executed, meaning there will be drift between the rotation timestamp and actual rotation. The new rotation timestamp offset includes this drift. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html by only forcing a new value on the set cadence.
+---
+
+# time_rotating (Resource)
+
+Manages a rotating time resource, which keeps a rotating UTC timestamp stored in the Terraform state and proposes resource recreation when the locally sourced current time is beyond the rotation time. This rotation only occurs when Terraform is executed, meaning there will be drift between the rotation timestamp and actual rotation. The new rotation timestamp offset includes this drift. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html) by only forcing a new value on the set cadence.
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```terraform
+resource "time_rotating" "example" {
+ rotation_days = 30
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `rfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `rotation_days` (Number) Number of days to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_hours` (Number) Number of hours to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_minutes` (Number) Number of minutes to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_months` (Number) Number of months to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_rfc3339` (String) Configure the rotation timestamp with an [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format of the offset timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `rotation_years` (Number) Number of years to add to the base timestamp to configure the rotation timestamp. When the current time has passed the rotation timestamp, the resource will trigger recreation. At least one of the 'rotation_' arguments must be configured.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. These conditions recreate the resource in addition to other rotation arguments. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of timestamp.
+- `hour` (Number) Number hour of timestamp.
+- `id` (String) RFC3339 format of the timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of timestamp.
+- `month` (Number) Number month of timestamp.
+- `second` (Number) Number second of timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of timestamp.
+
+## Import
+
+This resource can be imported using the base UTC RFC3339 value and rotation years, months, days, hours, and minutes, separated by commas (`,`), e.g. for 30 days
+
+```shell
+terraform import time_rotating.example 2020-02-12T06:36:13Z,0,0,30,0,0
+```
+
+Otherwise, to import with the rotation RFC3339 value, the base UTC RFC3339 value and rotation UTC RFC3339 value, separated by commas (`,`), e.g.
+
+```shell
+terraform import time_rotating.example 2020-02-12T06:36:13Z,2020-02-13T06:36:13Z
+```
+
+The `triggers` argument cannot be imported.
diff --git a/v0.10.0/docs/resources/sleep.md b/v0.10.0/docs/resources/sleep.md
new file mode 100644
index 0000000..efd83ae
--- /dev/null
+++ b/v0.10.0/docs/resources/sleep.md
@@ -0,0 +1,110 @@
+---
+page_title: "time_sleep Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a resource that delays creation and/or destruction, typically for further resources. This prevents cross-platform compatibility and destroy-time issues with using the local-exec provisioner https://www.terraform.io/docs/provisioners/local-exec.html.
+---
+
+# time_sleep (Resource)
+
+Manages a resource that delays creation and/or destruction, typically for further resources. This prevents cross-platform compatibility and destroy-time issues with using the [`local-exec` provisioner](https://www.terraform.io/docs/provisioners/local-exec.html).
+
+-> In many cases, this resource should be considered a workaround for issues that should be reported and handled in downstream Terraform Provider logic. Downstream resources can usually introduce or adjust retries in their code to handle time delay issues for all Terraform configurations or upstream resources can be improved to better wait for a resource to be fully ready and available.
+
+## Example Usage
+
+### Delay Create Usage
+
+```terraform
+# This resource will destroy (potentially immediately) after null_resource.next
+resource "null_resource" "previous" {}
+
+resource "time_sleep" "wait_30_seconds" {
+ depends_on = [null_resource.previous]
+
+ create_duration = "30s"
+}
+
+# This resource will create (at least) 30 seconds after null_resource.previous
+resource "null_resource" "next" {
+ depends_on = [time_sleep.wait_30_seconds]
+}
+```
+
+### Delay Destroy Usage
+
+```terraform
+# This resource will destroy (at least) 30 seconds after null_resource.next
+resource "null_resource" "previous" {}
+
+resource "time_sleep" "wait_30_seconds" {
+ depends_on = [null_resource.previous]
+
+ destroy_duration = "30s"
+}
+
+# This resource will create (potentially immediately) after null_resource.previous
+resource "null_resource" "next" {
+ depends_on = [time_sleep.wait_30_seconds]
+}
+```
+
+### Triggers Usage
+
+```terraform
+resource "aws_ram_resource_association" "example" {
+ resource_arn = aws_subnet.example.arn
+ resource_share_arn = aws_ram_resource_share.example.arn
+}
+
+# AWS resources shared via Resource Access Manager can take a few seconds to
+# propagate across AWS accounts after RAM returns a successful association.
+resource "time_sleep" "ram_resource_propagation" {
+ create_duration = "60s"
+
+ triggers = {
+ # This sets up a proper dependency on the RAM association
+ subnet_arn = aws_ram_resource_association.example.resource_arn
+ subnet_id = aws_subnet.example.id
+ }
+}
+
+resource "aws_db_subnet_group" "example" {
+ name = "example"
+
+ # Read the Subnet identifier "through" the time_sleep resource to ensure a
+ # proper dependency and that both will change together.
+ subnet_ids = [time_sleep.ram_resource_propagation.triggers["subnet_id"]]
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `create_duration` (String) [Time duration](https://golang.org/pkg/time/#ParseDuration) to delay resource creation. For example, `30s` for 30 seconds or `5m` for 5 minutes. Updating this value by itself will not trigger a delay.
+- `destroy_duration` (String) [Time duration](https://golang.org/pkg/time/#ParseDuration) to delay resource destroy. For example, `30s` for 30 seconds or `5m` for 5 minutes. Updating this value by itself will not trigger a delay. This value or any updates to it must be successfully applied into the Terraform state before destroying this resource to take effect.
+- `triggers` (Map of String) (Optional) Arbitrary map of values that, when changed, will run any creation or destroy delays again. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+
+## Import
+
+This resource can be imported with the `create_duration` and `destroy_duration`, separated by a comma (`,`).
+
+e.g. For 30 seconds create duration with no destroy duration:
+
+```shell
+terraform import time_sleep.example 30s,
+```
+
+e.g. For 30 seconds destroy duration with no create duration:
+
+```shell
+terraform import time_sleep.example ,30s
+```
+
+The `triggers` argument cannot be imported.
\ No newline at end of file
diff --git a/v0.10.0/docs/resources/static.md b/v0.10.0/docs/resources/static.md
new file mode 100644
index 0000000..1ba7d56
--- /dev/null
+++ b/v0.10.0/docs/resources/static.md
@@ -0,0 +1,77 @@
+---
+page_title: "time_static Resource - terraform-provider-time"
+subcategory: ""
+description: |-
+ Manages a static time resource, which keeps a locally sourced UTC timestamp stored in the Terraform state. This prevents perpetual differences caused by using the timestamp() function https://www.terraform.io/docs/configuration/functions/timestamp.html.
+---
+
+# time_static (Resource)
+
+Manages a static time resource, which keeps a locally sourced UTC timestamp stored in the Terraform state. This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html).
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+```terraform
+resource "time_static" "example" {}
+
+output "current_time" {
+ value = time_static.example.rfc3339
+}
+```
+
+### Triggers Usage
+
+```terraform
+resource "time_static" "ami_update" {
+ triggers = {
+ # Save the time each switch of an AMI id
+ ami_id = data.aws_ami.example.id
+ }
+}
+
+resource "aws_instance" "server" {
+ # Read the AMI id "through" the time_static resource to ensure that
+ # both will change together.
+ ami = time_static.ami_update.triggers.ami_id
+
+ tags = {
+ AmiUpdateTime = time_static.ami_update.rfc3339
+ }
+
+ # ... (other aws_instance arguments) ...
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Optional
+
+- `rfc3339` (String) Base timestamp in [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format (see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., `YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.
+- `triggers` (Map of String) Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. See [the main provider documentation](../index.md) for more information.
+
+### Read-Only
+
+- `day` (Number) Number day of timestamp.
+- `hour` (Number) Number hour of timestamp.
+- `id` (String) RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.
+- `minute` (Number) Number minute of timestamp.
+- `month` (Number) Number month of timestamp.
+- `second` (Number) Number second of timestamp.
+- `unix` (Number) Number of seconds since epoch time, e.g. `1581489373`.
+- `year` (Number) Number year of timestamp.
+
+
+## Import
+
+This resource can be imported using the UTC RFC3339 value, e.g.
+
+```shell
+terraform import time_static.example 2020-02-12T06:36:13Z
+```
+
+The `triggers` argument cannot be imported.
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/resource_triggers.tf b/v0.10.0/examples/resources/resource_triggers.tf
new file mode 100644
index 0000000..4e32f35
--- /dev/null
+++ b/v0.10.0/examples/resources/resource_triggers.tf
@@ -0,0 +1,18 @@
+resource "time_static" "ami_update" {
+ triggers = {
+ # Save the time each switch of an AMI id
+ ami_id = data.aws_ami.example.id
+ }
+}
+
+resource "aws_instance" "server" {
+ # Read the AMI id "through" the time_static resource to ensure that
+ # both will change together.
+ ami = time_static.ami_update.triggers.ami_id
+
+ tags = {
+ AmiUpdateTime = time_static.ami_update.rfc3339
+ }
+
+ # ... (other aws_instance arguments) ...
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_offset/import.sh b/v0.10.0/examples/resources/time_offset/import.sh
new file mode 100644
index 0000000..a5bb8f8
--- /dev/null
+++ b/v0.10.0/examples/resources/time_offset/import.sh
@@ -0,0 +1 @@
+terraform import time_offset.example 2020-02-12T06:36:13Z,0,0,7,0,0,0
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_offset/resource.tf b/v0.10.0/examples/resources/time_offset/resource.tf
new file mode 100644
index 0000000..8ee378f
--- /dev/null
+++ b/v0.10.0/examples/resources/time_offset/resource.tf
@@ -0,0 +1,7 @@
+resource "time_offset" "example" {
+ offset_days = 7
+}
+
+output "one_week_from_now" {
+ value = time_offset.example.rfc3339
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_offset/resource_multiple_offset.tf b/v0.10.0/examples/resources/time_offset/resource_multiple_offset.tf
new file mode 100644
index 0000000..40d7156
--- /dev/null
+++ b/v0.10.0/examples/resources/time_offset/resource_multiple_offset.tf
@@ -0,0 +1,8 @@
+resource "time_offset" "example" {
+ offset_years = 1
+ offset_months = 1
+}
+
+output "one_year_and_month_from_now" {
+ value = time_offset.example.rfc3339
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_offset/resource_triggers.tf b/v0.10.0/examples/resources/time_offset/resource_triggers.tf
new file mode 100644
index 0000000..f2359dc
--- /dev/null
+++ b/v0.10.0/examples/resources/time_offset/resource_triggers.tf
@@ -0,0 +1,20 @@
+resource "time_offset" "ami_update" {
+ triggers = {
+ # Save the time each switch of an AMI id
+ ami_id = data.aws_ami.example.id
+ }
+
+ offset_days = 7
+}
+
+resource "aws_instance" "server" {
+ # Read the AMI id "through" the time_offset resource to ensure that
+ # both will change together.
+ ami = time_offset.ami_update.triggers.ami_id
+
+ tags = {
+ ExpirationTime = time_offset.ami_update.rfc3339
+ }
+
+ # ... (other aws_instance arguments) ...
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_rotating/import_base_value.sh b/v0.10.0/examples/resources/time_rotating/import_base_value.sh
new file mode 100644
index 0000000..db073ee
--- /dev/null
+++ b/v0.10.0/examples/resources/time_rotating/import_base_value.sh
@@ -0,0 +1 @@
+terraform import time_rotating.example 2020-02-12T06:36:13Z,0,0,30,0,0
diff --git a/v0.10.0/examples/resources/time_rotating/import_rotation_value.sh b/v0.10.0/examples/resources/time_rotating/import_rotation_value.sh
new file mode 100644
index 0000000..ee43dbe
--- /dev/null
+++ b/v0.10.0/examples/resources/time_rotating/import_rotation_value.sh
@@ -0,0 +1 @@
+terraform import time_rotating.example 2020-02-12T06:36:13Z,2020-02-13T06:36:13Z
diff --git a/v0.10.0/examples/resources/time_rotating/resource.tf b/v0.10.0/examples/resources/time_rotating/resource.tf
new file mode 100644
index 0000000..c7df20f
--- /dev/null
+++ b/v0.10.0/examples/resources/time_rotating/resource.tf
@@ -0,0 +1,3 @@
+resource "time_rotating" "example" {
+ rotation_days = 30
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_sleep/import_create.sh b/v0.10.0/examples/resources/time_sleep/import_create.sh
new file mode 100644
index 0000000..05fe4b7
--- /dev/null
+++ b/v0.10.0/examples/resources/time_sleep/import_create.sh
@@ -0,0 +1 @@
+terraform import time_sleep.example 30s,
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_sleep/import_destroy.sh b/v0.10.0/examples/resources/time_sleep/import_destroy.sh
new file mode 100644
index 0000000..e5dceee
--- /dev/null
+++ b/v0.10.0/examples/resources/time_sleep/import_destroy.sh
@@ -0,0 +1 @@
+terraform import time_sleep.example ,30s
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_sleep/resource_delay_create.tf b/v0.10.0/examples/resources/time_sleep/resource_delay_create.tf
new file mode 100644
index 0000000..63b2ad6
--- /dev/null
+++ b/v0.10.0/examples/resources/time_sleep/resource_delay_create.tf
@@ -0,0 +1,13 @@
+# This resource will destroy (potentially immediately) after null_resource.next
+resource "null_resource" "previous" {}
+
+resource "time_sleep" "wait_30_seconds" {
+ depends_on = [null_resource.previous]
+
+ create_duration = "30s"
+}
+
+# This resource will create (at least) 30 seconds after null_resource.previous
+resource "null_resource" "next" {
+ depends_on = [time_sleep.wait_30_seconds]
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_sleep/resource_delay_destroy.tf b/v0.10.0/examples/resources/time_sleep/resource_delay_destroy.tf
new file mode 100644
index 0000000..86d8b3a
--- /dev/null
+++ b/v0.10.0/examples/resources/time_sleep/resource_delay_destroy.tf
@@ -0,0 +1,13 @@
+# This resource will destroy (at least) 30 seconds after null_resource.next
+resource "null_resource" "previous" {}
+
+resource "time_sleep" "wait_30_seconds" {
+ depends_on = [null_resource.previous]
+
+ destroy_duration = "30s"
+}
+
+# This resource will create (potentially immediately) after null_resource.previous
+resource "null_resource" "next" {
+ depends_on = [time_sleep.wait_30_seconds]
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_sleep/resource_triggers.tf b/v0.10.0/examples/resources/time_sleep/resource_triggers.tf
new file mode 100644
index 0000000..05c51ea
--- /dev/null
+++ b/v0.10.0/examples/resources/time_sleep/resource_triggers.tf
@@ -0,0 +1,24 @@
+resource "aws_ram_resource_association" "example" {
+ resource_arn = aws_subnet.example.arn
+ resource_share_arn = aws_ram_resource_share.example.arn
+}
+
+# AWS resources shared via Resource Access Manager can take a few seconds to
+# propagate across AWS accounts after RAM returns a successful association.
+resource "time_sleep" "ram_resource_propagation" {
+ create_duration = "60s"
+
+ triggers = {
+ # This sets up a proper dependency on the RAM association
+ subnet_arn = aws_ram_resource_association.example.resource_arn
+ subnet_id = aws_subnet.example.id
+ }
+}
+
+resource "aws_db_subnet_group" "example" {
+ name = "example"
+
+ # Read the Subnet identifier "through" the time_sleep resource to ensure a
+ # proper dependency and that both will change together.
+ subnet_ids = [time_sleep.ram_resource_propagation.triggers["subnet_id"]]
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_static/import.sh b/v0.10.0/examples/resources/time_static/import.sh
new file mode 100644
index 0000000..3c6ee9f
--- /dev/null
+++ b/v0.10.0/examples/resources/time_static/import.sh
@@ -0,0 +1 @@
+terraform import time_static.example 2020-02-12T06:36:13Z
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_static/resource.tf b/v0.10.0/examples/resources/time_static/resource.tf
new file mode 100644
index 0000000..5e60bba
--- /dev/null
+++ b/v0.10.0/examples/resources/time_static/resource.tf
@@ -0,0 +1,5 @@
+resource "time_static" "example" {}
+
+output "current_time" {
+ value = time_static.example.rfc3339
+}
\ No newline at end of file
diff --git a/v0.10.0/examples/resources/time_static/resource_triggers.tf b/v0.10.0/examples/resources/time_static/resource_triggers.tf
new file mode 100644
index 0000000..4e32f35
--- /dev/null
+++ b/v0.10.0/examples/resources/time_static/resource_triggers.tf
@@ -0,0 +1,18 @@
+resource "time_static" "ami_update" {
+ triggers = {
+ # Save the time each switch of an AMI id
+ ami_id = data.aws_ami.example.id
+ }
+}
+
+resource "aws_instance" "server" {
+ # Read the AMI id "through" the time_static resource to ensure that
+ # both will change together.
+ ami = time_static.ami_update.triggers.ami_id
+
+ tags = {
+ AmiUpdateTime = time_static.ami_update.rfc3339
+ }
+
+ # ... (other aws_instance arguments) ...
+}
\ No newline at end of file
diff --git a/v0.10.0/go.mod b/v0.10.0/go.mod
new file mode 100644
index 0000000..9444f86
--- /dev/null
+++ b/v0.10.0/go.mod
@@ -0,0 +1,63 @@
+module github.com/hashicorp/terraform-provider-time
+
+go 1.20
+
+require (
+ github.com/hashicorp/terraform-plugin-framework v1.4.2
+ github.com/hashicorp/terraform-plugin-framework-timetypes v0.3.0
+ github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
+ github.com/hashicorp/terraform-plugin-go v0.19.1
+ github.com/hashicorp/terraform-plugin-testing v1.6.0
+)
+
+require (
+ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
+ github.com/agext/levenshtein v1.2.2 // indirect
+ github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
+ github.com/cloudflare/circl v1.3.3 // indirect
+ github.com/fatih/color v1.13.0 // indirect
+ github.com/golang/protobuf v1.5.3 // indirect
+ github.com/google/go-cmp v0.6.0 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-checkpoint v0.5.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
+ github.com/hashicorp/go-hclog v1.5.0 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-plugin v1.5.2 // indirect
+ github.com/hashicorp/go-uuid v1.0.3 // indirect
+ github.com/hashicorp/go-version v1.6.0 // indirect
+ github.com/hashicorp/hc-install v0.6.1 // indirect
+ github.com/hashicorp/hcl/v2 v2.19.1 // indirect
+ github.com/hashicorp/logutils v1.0.0 // indirect
+ github.com/hashicorp/terraform-exec v0.19.0 // indirect
+ github.com/hashicorp/terraform-json v0.18.0 // indirect
+ github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect
+ github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0 // indirect
+ github.com/hashicorp/terraform-registry-address v0.2.3 // indirect
+ github.com/hashicorp/terraform-svchost v0.1.1 // indirect
+ github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect
+ github.com/kr/pretty v0.3.0 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.16 // indirect
+ github.com/mitchellh/copystructure v1.2.0 // indirect
+ github.com/mitchellh/go-testing-interface v1.14.1 // indirect
+ github.com/mitchellh/go-wordwrap v1.0.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/mitchellh/reflectwalk v1.0.2 // indirect
+ github.com/oklog/run v1.0.0 // indirect
+ github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
+ github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
+ github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
+ github.com/zclconf/go-cty v1.14.1 // indirect
+ golang.org/x/crypto v0.16.0 // indirect
+ golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819 // indirect
+ golang.org/x/mod v0.13.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
+ golang.org/x/sys v0.15.0 // indirect
+ golang.org/x/text v0.14.0 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
+ google.golang.org/grpc v1.59.0 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
+)
diff --git a/v0.10.0/go.sum b/v0.10.0/go.sum
new file mode 100644
index 0000000..38aeb6b
--- /dev/null
+++ b/v0.10.0/go.sum
@@ -0,0 +1,221 @@
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
+github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
+github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
+github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
+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/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
+github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
+github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
+github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA=
+github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
+github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
+github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
+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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
+github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
+github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY=
+github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/protobuf v1.1.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.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.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/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=
+github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI=
+github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs=
+github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
+github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT1G2Y=
+github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
+github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
+github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/hc-install v0.6.1 h1:IGxShH7AVhPaSuSJpKtVi/EFORNjO+OYVJJrAtGG2mY=
+github.com/hashicorp/hc-install v0.6.1/go.mod h1:0fW3jpg+wraYSnFDJ6Rlie3RvLf1bIqVIkzoon4KoVE=
+github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI=
+github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
+github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/terraform-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM=
+github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg=
+github.com/hashicorp/terraform-json v0.18.0 h1:pCjgJEqqDESv4y0Tzdqfxr/edOIGkjs8keY42xfNBwU=
+github.com/hashicorp/terraform-json v0.18.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk=
+github.com/hashicorp/terraform-plugin-framework v1.4.2 h1:P7a7VP1GZbjc4rv921Xy5OckzhoiO3ig6SGxwelD2sI=
+github.com/hashicorp/terraform-plugin-framework v1.4.2/go.mod h1:GWl3InPFZi2wVQmdVnINPKys09s9mLmTZr95/ngLnbY=
+github.com/hashicorp/terraform-plugin-framework-timetypes v0.3.0 h1:egR4InfakWkgepZNUATWGwkrPhaAYOTEybPfEol+G/I=
+github.com/hashicorp/terraform-plugin-framework-timetypes v0.3.0/go.mod h1:9vjvl36aY1p6KltaA5QCvGC5hdE/9t4YuhGftw6WOgE=
+github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 h1:HOjBuMbOEzl7snOdOoUfE2Jgeto6JOjLVQ39Ls2nksc=
+github.com/hashicorp/terraform-plugin-framework-validators v0.12.0/go.mod h1:jfHGE/gzjxYz6XoUwi/aYiiKrJDeutQNUtGQXkaHklg=
+github.com/hashicorp/terraform-plugin-go v0.19.1 h1:lf/jTGTeELcz5IIbn/94mJdmnTjRYm6S6ct/JqCSr50=
+github.com/hashicorp/terraform-plugin-go v0.19.1/go.mod h1:5NMIS+DXkfacX6o5HCpswda5yjkSYfKzn1Nfl9l+qRs=
+github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
+github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow=
+github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0 h1:X7vB6vn5tON2b49ILa4W7mFAsndeqJ7bZFOGbVO+0Cc=
+github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0/go.mod h1:ydFcxbdj6klCqYEPkPvdvFKiNGKZLUs+896ODUXCyao=
+github.com/hashicorp/terraform-plugin-testing v1.6.0 h1:Wsnfh+7XSVRfwcr2jZYHsnLOnZl7UeaOBvsx6dl/608=
+github.com/hashicorp/terraform-plugin-testing v1.6.0/go.mod h1:cJGG0/8j9XhHaJZRC+0sXFI4uzqQZ9Az4vh6C4GJpFE=
+github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI=
+github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM=
+github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ=
+github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
+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/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
+github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+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 v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+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-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
+github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
+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.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
+github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
+github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
+github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
+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/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
+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=
+github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
+github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
+github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
+github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
+github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA=
+github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
+golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
+golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
+golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819 h1:EDuYyU/MkFXllv9QF9819VlI9a4tzGuCbhG0ExK9o1U=
+golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
+golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+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-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
+google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
+google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/v0.10.0/internal/modifiers/timemodifier/replace_if_outdated.go b/v0.10.0/internal/modifiers/timemodifier/replace_if_outdated.go
new file mode 100644
index 0000000..0a49c75
--- /dev/null
+++ b/v0.10.0/internal/modifiers/timemodifier/replace_if_outdated.go
@@ -0,0 +1,41 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package timemodifier
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+)
+
+func ReplaceIfOutdated(ctx context.Context, req planmodifier.StringRequest, resp *stringplanmodifier.RequiresReplaceIfFuncResponse) {
+ if req.State.Raw.IsNull() {
+ // if we're creating the resource, no need to delete and
+ // recreate it
+ return
+ }
+
+ if req.Plan.Raw.IsNull() {
+ // if we're deleting the resource, no need to delete and
+ // recreate it
+ return
+ }
+
+ rotationTimestamp, err := time.Parse(time.RFC3339, req.StateValue.ValueString())
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "replaceIfOutdated plan modifier error",
+ "The rotation rfc3339 timestamp that was supplied could not be parsed as RFC3339.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ now := time.Now().UTC()
+
+ resp.RequiresReplace = now.After(rotationTimestamp)
+}
diff --git a/v0.10.0/internal/provider/provider.go b/v0.10.0/internal/provider/provider.go
new file mode 100644
index 0000000..21a7d9d
--- /dev/null
+++ b/v0.10.0/internal/provider/provider.go
@@ -0,0 +1,46 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "context"
+
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/provider"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+)
+
+func New() provider.Provider {
+ return &timeProvider{}
+}
+
+var (
+ _ provider.Provider = (*timeProvider)(nil)
+)
+
+type timeProvider struct{}
+
+func (p *timeProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
+ resp.TypeName = "time"
+}
+
+func (p *timeProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
+
+}
+
+func (p *timeProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
+ return nil
+}
+
+func (p *timeProvider) Resources(ctx context.Context) []func() resource.Resource {
+ return []func() resource.Resource{
+ NewTimeOffsetResource,
+ NewTimeRotatingResource,
+ NewTimeSleepResource,
+ NewTimeStaticResource,
+ }
+}
+
+func (p *timeProvider) Schema(context.Context, provider.SchemaRequest, *provider.SchemaResponse) {
+}
diff --git a/v0.10.0/internal/provider/provider_test.go b/v0.10.0/internal/provider/provider_test.go
new file mode 100644
index 0000000..64ef92a
--- /dev/null
+++ b/v0.10.0/internal/provider/provider_test.go
@@ -0,0 +1,90 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-framework/providerserver"
+
+ "github.com/hashicorp/terraform-plugin-go/tfprotov5"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+)
+
+func protoV5ProviderFactories() map[string]func() (tfprotov5.ProviderServer, error) {
+ return map[string]func() (tfprotov5.ProviderServer, error){
+ "time": providerserver.NewProtocol5WithError(New()),
+ }
+}
+
+func providerVersion080() map[string]resource.ExternalProvider {
+ return map[string]resource.ExternalProvider{
+ "time": {
+ VersionConstraint: "0.8.0",
+ Source: "hashicorp/time",
+ },
+ }
+}
+
+func testCheckAttributeValuesDiffer(i *string, j *string) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ if testStringValue(i) == testStringValue(j) {
+ return fmt.Errorf("attribute values are the same")
+ }
+
+ return nil
+ }
+}
+
+func testCheckAttributeValuesSame(i *string, j *string) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ if testStringValue(i) != testStringValue(j) {
+ return fmt.Errorf("attribute values are different")
+ }
+
+ return nil
+ }
+}
+
+//nolint:unparam
+func testExtractResourceAttr(resourceName string, attributeName string, attributeValue *string) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ rs, ok := s.RootModule().Resources[resourceName]
+
+ if !ok {
+ return fmt.Errorf("resource name %s not found in state", resourceName)
+ }
+
+ attrValue, ok := rs.Primary.Attributes[attributeName]
+
+ if !ok {
+ return fmt.Errorf("attribute %s not found in resource %s state", attributeName, resourceName)
+ }
+
+ *attributeValue = attrValue
+
+ return nil
+ }
+}
+
+// Certain testing requires time differences that are too fast for unit testing.
+// Sleeping for a second or two seems pragmatic in our testing.
+func testSleep(seconds int) resource.TestCheckFunc {
+ return func(s *terraform.State) error {
+ time.Sleep(time.Duration(seconds) * time.Second)
+
+ return nil
+ }
+}
+
+func testStringValue(sPtr *string) string {
+ if sPtr == nil {
+ return ""
+ }
+
+ return *sPtr
+}
diff --git a/v0.10.0/internal/provider/resource_time_offset.go b/v0.10.0/internal/provider/resource_time_offset.go
new file mode 100644
index 0000000..c377bc8
--- /dev/null
+++ b/v0.10.0/internal/provider/resource_time_offset.go
@@ -0,0 +1,448 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
+ "github.com/hashicorp/terraform-plugin-framework-validators/resourcevalidator"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+var (
+ _ resource.Resource = (*timeOffsetResource)(nil)
+ _ resource.ResourceWithImportState = (*timeOffsetResource)(nil)
+ _ resource.ResourceWithModifyPlan = (*timeOffsetResource)(nil)
+ _ resource.ResourceWithConfigValidators = (*timeOffsetResource)(nil)
+)
+
+func NewTimeOffsetResource() resource.Resource {
+ return &timeOffsetResource{}
+}
+
+type timeOffsetResource struct{}
+
+func (t timeOffsetResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_offset"
+}
+
+func (t timeOffsetResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Manages an offset time resource, which keeps an UTC timestamp stored in the Terraform state that is" +
+ " offset from a locally sourced base timestamp. This prevents perpetual differences caused " +
+ "by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html).",
+ Attributes: map[string]schema.Attribute{
+ "base_rfc3339": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "Base timestamp in " +
+ "[RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format " +
+ "(see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., " +
+ "`YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.",
+ Optional: true,
+ Computed: true,
+ },
+ "day": schema.Int64Attribute{
+ Description: "Number day of offset timestamp.",
+ Computed: true,
+ },
+ "hour": schema.Int64Attribute{
+ Description: "Number hour of offset timestamp.",
+ Computed: true,
+ },
+ "triggers": schema.MapAttribute{
+ Description: "Arbitrary map of values that, when changed, will trigger a new base timestamp value " +
+ "to be saved. See [the main provider documentation](../index.md) for more information.",
+ ElementType: types.StringType,
+ Optional: true,
+ PlanModifiers: []planmodifier.Map{
+ mapplanmodifier.RequiresReplace(),
+ },
+ },
+ "minute": schema.Int64Attribute{
+ Description: "Number minute of offset timestamp.",
+ Computed: true,
+ },
+ "month": schema.Int64Attribute{
+ Description: "Number month of offset timestamp.",
+ Computed: true,
+ },
+ "offset_days": schema.Int64Attribute{
+ Description: "Number of days to offset the base timestamp. At least one of the 'offset_' arguments must be configured.",
+ Optional: true,
+ },
+ "offset_hours": schema.Int64Attribute{
+ Description: " Number of hours to offset the base timestamp. At least one of the 'offset_' arguments must be configured.",
+ Optional: true,
+ },
+ "offset_minutes": schema.Int64Attribute{
+ Description: "Number of minutes to offset the base timestamp. At least one of the 'offset_' arguments must be configured.",
+ Optional: true,
+ },
+ "offset_months": schema.Int64Attribute{
+ Description: "Number of months to offset the base timestamp. At least one of the 'offset_' arguments must be configured.",
+ Optional: true,
+ },
+ "offset_seconds": schema.Int64Attribute{
+ Description: "Number of seconds to offset the base timestamp. At least one of the 'offset_' arguments must be configured.",
+ Optional: true,
+ },
+ "offset_years": schema.Int64Attribute{
+ Description: "Number of years to offset the base timestamp. At least one of the 'offset_' arguments must be configured.",
+ Optional: true,
+ },
+ "rfc3339": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.",
+ Computed: true,
+ },
+ "second": schema.Int64Attribute{
+ Description: "Number second of offset timestamp.",
+ Computed: true,
+ },
+ "unix": schema.Int64Attribute{
+ Description: "Number of seconds since epoch time, e.g. `1581489373`.",
+ Computed: true,
+ },
+ "year": schema.Int64Attribute{
+ Description: "Number year of offset timestamp.",
+ Computed: true,
+ },
+ "id": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.",
+ Computed: true,
+ },
+ },
+ }
+}
+
+func (t timeOffsetResource) ConfigValidators(_ context.Context) []resource.ConfigValidator {
+ return []resource.ConfigValidator{
+ resourcevalidator.AtLeastOneOf(
+ path.MatchRoot("offset_seconds"),
+ path.MatchRoot("offset_minutes"),
+ path.MatchRoot("offset_hours"),
+ path.MatchRoot("offset_days"),
+ path.MatchRoot("offset_months"),
+ path.MatchRoot("offset_years"),
+ ),
+ }
+}
+
+func (t timeOffsetResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
+ // Plan does not need to be modified when the resource is being destroyed.
+ if req.Plan.Raw.IsNull() {
+ return
+ }
+
+ // Plan only needs modifying if the resource already exists as the purpose of
+ // the plan modifier is to show updated attribute values on CLI.
+ if req.State.Raw.IsNull() {
+ return
+ }
+
+ var state, plan timeOffsetModelV0
+
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ diags = req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ if state.OffsetYears == plan.OffsetYears &&
+ state.OffsetMonths == plan.OffsetMonths &&
+ state.OffsetDays == plan.OffsetDays &&
+ state.OffsetHours == plan.OffsetHours &&
+ state.OffsetMinutes == plan.OffsetMinutes &&
+ state.OffsetSeconds == plan.OffsetSeconds {
+ return
+ }
+
+ var baseRFC3339 timetypes.RFC3339
+
+ diags = req.Plan.GetAttribute(ctx, path.Root("base_rfc3339"), &baseRFC3339)
+
+ resp.Diagnostics = append(resp.Diagnostics, diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // baseRFC3339 could be unknown if there is no value set in the config as the attribute is
+ // optional and computed. If base_rfc3339 is not set in config then the previous value from
+ // state is used and propagated to the update function.
+ if baseRFC3339.IsUnknown() {
+ resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("base_rfc3339"), &baseRFC3339)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ }
+
+ timestamp, diags := baseRFC3339.ValueRFC3339Time()
+
+ resp.Diagnostics.Append(diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ setOffsetValues(&plan, timestamp)
+
+ diags = resp.Plan.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeOffsetResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ var importedState timeOffsetModelV0
+ var err error
+
+ id := req.ID
+
+ idParts := strings.Split(id, ",")
+
+ if len(idParts) != 7 {
+ resp.Diagnostics.AddError(
+ "Unexpected Format of ID",
+ fmt.Sprintf("Unexpected format of ID (%q), expected BASETIMESTAMP,YEARS,MONTHS,DAYS,HOURS,MINUTES,SECONDS", id))
+
+ return
+ }
+
+ if idParts[0] == "" || (idParts[1] == "" && idParts[2] == "" && idParts[3] == "" && idParts[4] == "" && idParts[5] == "" && idParts[6] == "") {
+ resp.Diagnostics.AddError(
+ "Unexpected Format of ID",
+ fmt.Sprintf("Unexpected format of ID (%q), expected BASETIMESTAMP,YEARS,MONTHS,DAYS,HOURS,MINUTES,SECONDS where at least one offset value is non-empty", id))
+
+ return
+ }
+
+ baseRfc3339 := idParts[0]
+
+ importedState.OffsetYears, err = offsetToInt64(idParts[1])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time offset error",
+ "The offset_years parameter that was supplied could not be parsed as Int64.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ importedState.OffsetMonths, err = offsetToInt64(idParts[2])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time offset error",
+ "The offset_months parameter that was supplied could not be parsed as Int64.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ importedState.OffsetDays, err = offsetToInt64(idParts[3])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time offset error",
+ "The offset_days parameter that was supplied could not be parsed as Int64.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ importedState.OffsetHours, err = offsetToInt64(idParts[4])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time offset error",
+ "The offset_hours parameter that was supplied could not be parsed as Int64.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ importedState.OffsetMinutes, err = offsetToInt64(idParts[5])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time offset error",
+ "The offset_minutes parameter that was supplied could not be parsed as Int64.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ importedState.OffsetSeconds, err = offsetToInt64(idParts[6])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time offset error",
+ "The offset_seconds parameter that was supplied could not be parsed as Int64.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ timestamp, err := time.Parse(time.RFC3339, baseRfc3339)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Create time offset error",
+ "The base_rfc3339 timestamp that was supplied could not be parsed as RFC3339.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ setOffsetValues(&importedState, timestamp)
+ importedState.Triggers = types.MapValueMust(types.StringType, map[string]attr.Value{})
+
+ diags := resp.State.Set(ctx, importedState)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeOffsetResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan timeOffsetModelV0
+
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ timestamp := time.Now().UTC()
+
+ if plan.BaseRFC3339.ValueString() != "" {
+ baseRFC3339, diags := plan.BaseRFC3339.ValueRFC3339Time()
+
+ resp.Diagnostics.Append(diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ timestamp = baseRFC3339
+ }
+
+ setOffsetValues(&plan, timestamp)
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeOffsetResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+
+}
+
+func (t timeOffsetResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan timeOffsetModelV0
+
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ timestamp, diags := plan.BaseRFC3339.ValueRFC3339Time()
+
+ resp.Diagnostics.Append(diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ setOffsetValues(&plan, timestamp)
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeOffsetResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+
+}
+
+type timeOffsetModelV0 struct {
+ BaseRFC3339 timetypes.RFC3339 `tfsdk:"base_rfc3339"`
+ Triggers types.Map `tfsdk:"triggers"`
+ Year types.Int64 `tfsdk:"year"`
+ Month types.Int64 `tfsdk:"month"`
+ Day types.Int64 `tfsdk:"day"`
+ Hour types.Int64 `tfsdk:"hour"`
+ Minute types.Int64 `tfsdk:"minute"`
+ Second types.Int64 `tfsdk:"second"`
+ OffsetYears types.Int64 `tfsdk:"offset_years"`
+ OffsetMonths types.Int64 `tfsdk:"offset_months"`
+ OffsetDays types.Int64 `tfsdk:"offset_days"`
+ OffsetHours types.Int64 `tfsdk:"offset_hours"`
+ OffsetMinutes types.Int64 `tfsdk:"offset_minutes"`
+ OffsetSeconds types.Int64 `tfsdk:"offset_seconds"`
+ RFC3339 timetypes.RFC3339 `tfsdk:"rfc3339"`
+ Unix types.Int64 `tfsdk:"unix"`
+ ID timetypes.RFC3339 `tfsdk:"id"`
+}
+
+func setOffsetValues(plan *timeOffsetModelV0, timestamp time.Time) {
+ var offsetTimestamp = timestamp
+
+ if plan.OffsetDays.ValueInt64() != 0 {
+ offsetTimestamp = offsetTimestamp.AddDate(0, 0, int(plan.OffsetDays.ValueInt64()))
+ }
+
+ if plan.OffsetHours.ValueInt64() != 0 {
+ hours := time.Duration(plan.OffsetHours.ValueInt64()) * time.Hour
+ offsetTimestamp = offsetTimestamp.Add(hours)
+ }
+
+ if plan.OffsetMinutes.ValueInt64() != 0 {
+ minutes := time.Duration(plan.OffsetMinutes.ValueInt64()) * time.Minute
+ offsetTimestamp = offsetTimestamp.Add(minutes)
+ }
+
+ if plan.OffsetMonths.ValueInt64() != 0 {
+ offsetTimestamp = offsetTimestamp.AddDate(0, int(plan.OffsetMonths.ValueInt64()), 0)
+ }
+
+ if plan.OffsetSeconds.ValueInt64() != 0 {
+ seconds := time.Duration(plan.OffsetSeconds.ValueInt64()) * time.Second
+ offsetTimestamp = offsetTimestamp.Add(seconds)
+ }
+
+ if plan.OffsetYears.ValueInt64() != 0 {
+ offsetTimestamp = offsetTimestamp.AddDate(int(plan.OffsetYears.ValueInt64()), 0, 0)
+ }
+
+ plan.BaseRFC3339 = timetypes.NewRFC3339TimeValue(timestamp)
+ plan.Year = types.Int64Value(int64(offsetTimestamp.Year()))
+ plan.Month = types.Int64Value(int64(offsetTimestamp.Month()))
+ plan.Day = types.Int64Value(int64(offsetTimestamp.Day()))
+ plan.Hour = types.Int64Value(int64(offsetTimestamp.Hour()))
+ plan.Minute = types.Int64Value(int64(offsetTimestamp.Minute()))
+ plan.Second = types.Int64Value(int64(offsetTimestamp.Second()))
+ plan.RFC3339 = timetypes.NewRFC3339TimeValue(offsetTimestamp)
+ plan.Unix = types.Int64Value(offsetTimestamp.Unix())
+ plan.ID = timetypes.NewRFC3339TimeValue(timestamp)
+}
+
+func offsetToInt64(offsetStr string) (types.Int64, error) {
+ offset := types.Int64Null()
+
+ if offsetStr != "" {
+ offsetInt, err := strconv.ParseInt(offsetStr, 10, 64)
+ if err != nil {
+ return offset, fmt.Errorf("could not parse offset (%q) as int: %w", offsetStr, err)
+ }
+
+ offset = types.Int64Value(offsetInt)
+ }
+
+ return offset, nil
+}
diff --git a/v0.10.0/internal/provider/resource_time_offset_test.go b/v0.10.0/internal/provider/resource_time_offset_test.go
new file mode 100644
index 0000000..e273c8c
--- /dev/null
+++ b/v0.10.0/internal/provider/resource_time_offset_test.go
@@ -0,0 +1,572 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "fmt"
+ "regexp"
+ "strconv"
+ "testing"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+)
+
+func TestAccTimeOffset_Triggers(t *testing.T) {
+ resourceName := "time_offset.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeOffsetTriggers1("key1", "value1"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "triggers.%", "1"),
+ resource.TestCheckResourceAttr(resourceName, "triggers.key1", "value1"),
+ resource.TestCheckResourceAttr(resourceName, "offset_days", "1"),
+ resource.TestCheckNoResourceAttr(resourceName, "offset_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "offset_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "offset_minutes"),
+ resource.TestCheckNoResourceAttr(resourceName, "offset_seconds"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ testSleep(1),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeOffsetImportStateIdFunc(),
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"triggers"},
+ },
+ {
+ Config: testAccConfigTimeOffsetTriggers1("key1", "value1updated"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "triggers.%", "1"),
+ resource.TestCheckResourceAttr(resourceName, "triggers.key1", "value1updated"),
+ resource.TestCheckResourceAttr(resourceName, "offset_days", "1"),
+ resource.TestCheckNoResourceAttr(resourceName, "offset_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "offset_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "offset_minutes"),
+ resource.TestCheckNoResourceAttr(resourceName, "offset_seconds"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_OffsetDays(t *testing.T) {
+ resourceName := "time_offset.test"
+ timestamp := time.Now().UTC()
+ offsetTimestamp := timestamp.AddDate(0, 0, 7)
+ offsetTimestampUpdated := timestamp.AddDate(0, 0, 8)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeOffsetOffsetDays(timestamp.Format(time.RFC3339), 7),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_days", "7"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeOffsetImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ {
+ Config: testAccConfigTimeOffsetOffsetDays(timestamp.Format(time.RFC3339), 8),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestampUpdated.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestampUpdated.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestampUpdated.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestampUpdated.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_days", "8"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestampUpdated.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestampUpdated.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestampUpdated.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestampUpdated.Year())),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_OffsetHours(t *testing.T) {
+ resourceName := "time_offset.test"
+ timestamp := time.Now().UTC()
+ offsetTimestamp := timestamp.Add(1 * time.Hour)
+ offsetTimestampUpdated := timestamp.Add(2 * time.Hour)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeOffsetOffsetHours(timestamp.Format(time.RFC3339), 1),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_hours", "1"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeOffsetImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ {
+ Config: testAccConfigTimeOffsetOffsetHours(timestamp.Format(time.RFC3339), 2),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestampUpdated.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestampUpdated.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestampUpdated.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestampUpdated.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_hours", "2"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestampUpdated.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestampUpdated.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestampUpdated.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestampUpdated.Year())),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_OffsetMinutes(t *testing.T) {
+ resourceName := "time_offset.test"
+ timestamp := time.Now().UTC()
+ offsetTimestamp := timestamp.Add(1 * time.Minute)
+ offsetTimestampUpdated := timestamp.Add(2 * time.Minute)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeOffsetOffsetMinutes(timestamp.Format(time.RFC3339), 1),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_minutes", "1"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeOffsetImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ {
+ Config: testAccConfigTimeOffsetOffsetMinutes(timestamp.Format(time.RFC3339), 2),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestampUpdated.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestampUpdated.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestampUpdated.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestampUpdated.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_minutes", "2"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestampUpdated.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestampUpdated.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestampUpdated.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestampUpdated.Year())),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_OffsetMonths(t *testing.T) {
+ resourceName := "time_offset.test"
+ timestamp := time.Now().UTC()
+ offsetTimestamp := timestamp.AddDate(0, 3, 0)
+ offsetTimestampUpdated := timestamp.AddDate(0, 4, 0)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeOffsetOffsetMonths(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_months", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeOffsetImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ {
+ Config: testAccConfigTimeOffsetOffsetMonths(timestamp.Format(time.RFC3339), 4),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestampUpdated.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestampUpdated.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestampUpdated.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestampUpdated.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_months", "4"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestampUpdated.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestampUpdated.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestampUpdated.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestampUpdated.Year())),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_OffsetSeconds(t *testing.T) {
+ resourceName := "time_offset.test"
+ timestamp := time.Now().UTC()
+ offsetTimestamp := timestamp.Add(1 * time.Second)
+ offsetTimestampUpdated := timestamp.Add(2 * time.Second)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeOffsetOffsetSeconds(timestamp.Format(time.RFC3339), 1),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_seconds", "1"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeOffsetImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ {
+ Config: testAccConfigTimeOffsetOffsetSeconds(timestamp.Format(time.RFC3339), 2),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestampUpdated.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestampUpdated.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestampUpdated.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestampUpdated.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_seconds", "2"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestampUpdated.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestampUpdated.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestampUpdated.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestampUpdated.Year())),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_OffsetYears(t *testing.T) {
+ resourceName := "time_offset.test"
+ timestamp := time.Now().UTC()
+ offsetTimestamp := timestamp.AddDate(3, 0, 0)
+ offsetTimestampUpdated := timestamp.AddDate(4, 0, 0)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeOffsetOffsetYears(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_years", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeOffsetImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ {
+ Config: testAccConfigTimeOffsetOffsetYears(timestamp.Format(time.RFC3339), 4),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestampUpdated.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestampUpdated.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestampUpdated.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestampUpdated.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_years", "4"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestampUpdated.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestampUpdated.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestampUpdated.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestampUpdated.Year())),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_OffsetYearsAndMonths(t *testing.T) {
+ resourceName := "time_offset.test"
+ timestamp := time.Now().UTC()
+ offsetTimestamp := timestamp.AddDate(3, 3, 0)
+ offsetTimestampUpdated := timestamp.AddDate(4, 4, 0)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeOffsetOffsetYearsAndMonths(timestamp.Format(time.RFC3339), 3, 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_years", "3"),
+ resource.TestCheckResourceAttr(resourceName, "offset_months", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeOffsetImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ {
+ Config: testAccConfigTimeOffsetOffsetYearsAndMonths(timestamp.Format(time.RFC3339), 4, 4),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestampUpdated.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestampUpdated.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestampUpdated.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestampUpdated.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_years", "4"),
+ resource.TestCheckResourceAttr(resourceName, "offset_months", "4"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestampUpdated.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestampUpdated.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestampUpdated.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestampUpdated.Year())),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_Upgrade(t *testing.T) {
+ resourceName := "time_offset.test"
+ timestamp := time.Now().UTC()
+ offsetTimestamp := timestamp.AddDate(3, 0, 0)
+
+ resource.Test(t, resource.TestCase{
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ ExternalProviders: providerVersion080(),
+ Config: testAccConfigTimeOffsetOffsetYears(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_years", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ {
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ Config: testAccConfigTimeOffsetOffsetYears(timestamp.Format(time.RFC3339), 3),
+ PlanOnly: true,
+ },
+ {
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ Config: testAccConfigTimeOffsetOffsetYears(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "base_rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "day", strconv.Itoa(offsetTimestamp.Day())),
+ resource.TestCheckResourceAttr(resourceName, "hour", strconv.Itoa(offsetTimestamp.Hour())),
+ resource.TestCheckResourceAttr(resourceName, "minute", strconv.Itoa(offsetTimestamp.Minute())),
+ resource.TestCheckResourceAttr(resourceName, "month", strconv.Itoa(int(offsetTimestamp.Month()))),
+ resource.TestCheckResourceAttr(resourceName, "offset_years", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", offsetTimestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", strconv.Itoa(offsetTimestamp.Second())),
+ resource.TestCheckResourceAttr(resourceName, "unix", strconv.Itoa(int(offsetTimestamp.Unix()))),
+ resource.TestCheckResourceAttr(resourceName, "year", strconv.Itoa(offsetTimestamp.Year())),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeOffset_Validators(t *testing.T) {
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: fmt.Sprintf(`resource "time_offset" "test" {
+ base_rfc3339 = %q
+ }`, timestamp.Format(time.RFC3339)),
+ ExpectError: regexp.MustCompile(`.*Error: Missing Attribute Configuration`),
+ },
+ },
+ })
+}
+
+func testAccTimeOffsetImportStateIdFunc() resource.ImportStateIdFunc {
+ return func(s *terraform.State) (string, error) {
+ resourceName := "time_offset.test"
+ rs, ok := s.RootModule().Resources[resourceName]
+ if !ok {
+ return "", fmt.Errorf("Not found: %s", resourceName)
+ }
+
+ offsetYears := rs.Primary.Attributes["offset_years"]
+ offsetMonths := rs.Primary.Attributes["offset_months"]
+ offsetDays := rs.Primary.Attributes["offset_days"]
+ offsetHours := rs.Primary.Attributes["offset_hours"]
+ offsetMinutes := rs.Primary.Attributes["offset_minutes"]
+ offsetSeconds := rs.Primary.Attributes["offset_seconds"]
+
+ return fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s", rs.Primary.ID, offsetYears, offsetMonths, offsetDays, offsetHours, offsetMinutes, offsetSeconds), nil
+ }
+}
+
+func testAccConfigTimeOffsetTriggers1(keeperKey1 string, keeperKey2 string) string {
+ return fmt.Sprintf(`
+resource "time_offset" "test" {
+ triggers = {
+ %[1]q = %[2]q
+ }
+ offset_days = 1
+}
+`, keeperKey1, keeperKey2)
+}
+
+func testAccConfigTimeOffsetOffsetDays(baseRfc3339 string, offsetDays int) string {
+ return fmt.Sprintf(`
+resource "time_offset" "test" {
+ base_rfc3339 = %[1]q
+ offset_days = %[2]d
+}
+`, baseRfc3339, offsetDays)
+}
+
+func testAccConfigTimeOffsetOffsetHours(baseRfc3339 string, offsetHours int) string {
+ return fmt.Sprintf(`
+resource "time_offset" "test" {
+ base_rfc3339 = %[1]q
+ offset_hours = %[2]d
+}
+`, baseRfc3339, offsetHours)
+}
+
+func testAccConfigTimeOffsetOffsetMinutes(baseRfc3339 string, offsetMinutes int) string {
+ return fmt.Sprintf(`
+resource "time_offset" "test" {
+ base_rfc3339 = %[1]q
+ offset_minutes = %[2]d
+}
+`, baseRfc3339, offsetMinutes)
+}
+
+func testAccConfigTimeOffsetOffsetMonths(baseRfc3339 string, offsetMonths int) string {
+ return fmt.Sprintf(`
+resource "time_offset" "test" {
+ base_rfc3339 = %[1]q
+ offset_months = %[2]d
+}
+`, baseRfc3339, offsetMonths)
+}
+
+func testAccConfigTimeOffsetOffsetSeconds(baseRfc3339 string, offsetSeconds int) string {
+ return fmt.Sprintf(`
+resource "time_offset" "test" {
+ base_rfc3339 = %[1]q
+ offset_seconds = %[2]d
+}
+`, baseRfc3339, offsetSeconds)
+}
+
+func testAccConfigTimeOffsetOffsetYears(baseRfc3339 string, offsetYears int) string {
+ return fmt.Sprintf(`
+resource "time_offset" "test" {
+ base_rfc3339 = %[1]q
+ offset_years = %[2]d
+}
+`, baseRfc3339, offsetYears)
+}
+
+func testAccConfigTimeOffsetOffsetYearsAndMonths(baseRfc3339 string, offsetYears int, offsetMonths int) string {
+ return fmt.Sprintf(`
+resource "time_offset" "test" {
+ base_rfc3339 = %[1]q
+ offset_years = %[2]d
+ offset_months = %[3]d
+}
+`, baseRfc3339, offsetYears, offsetMonths)
+}
diff --git a/v0.10.0/internal/provider/resource_time_rotating.go b/v0.10.0/internal/provider/resource_time_rotating.go
new file mode 100644
index 0000000..bee8d12
--- /dev/null
+++ b/v0.10.0/internal/provider/resource_time_rotating.go
@@ -0,0 +1,625 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "context"
+ "fmt"
+ "log"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
+ "github.com/hashicorp/terraform-plugin-framework-validators/resourcevalidator"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/int64validator"
+
+ "github.com/hashicorp/terraform-provider-time/internal/modifiers/timemodifier"
+)
+
+var (
+ _ resource.Resource = (*timeRotatingResource)(nil)
+ _ resource.ResourceWithImportState = (*timeRotatingResource)(nil)
+ _ resource.ResourceWithModifyPlan = (*timeRotatingResource)(nil)
+ _ resource.ResourceWithConfigValidators = (*timeRotatingResource)(nil)
+)
+
+func NewTimeRotatingResource() resource.Resource {
+ return &timeRotatingResource{}
+}
+
+type timeRotatingResource struct{}
+
+func (t timeRotatingResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_rotating"
+}
+
+func (t timeRotatingResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Manages a rotating time resource, which keeps a rotating UTC timestamp stored in the Terraform " +
+ "state and proposes resource recreation when the locally sourced current time is beyond the rotation time. " +
+ "This rotation only occurs when Terraform is executed, meaning there will be drift between the rotation " +
+ "timestamp and actual rotation. The new rotation timestamp offset includes this drift. " +
+ "This prevents perpetual differences caused by using the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html) " +
+ "by only forcing a new value on the set cadence.",
+ Attributes: map[string]schema.Attribute{
+ "day": schema.Int64Attribute{
+ Description: "Number day of timestamp.",
+ Computed: true,
+ },
+ "rotation_days": schema.Int64Attribute{
+ Description: "Number of days to add to the base timestamp to configure the rotation timestamp. " +
+ "When the current time has passed the rotation timestamp, the resource will trigger recreation. " +
+ "At least one of the 'rotation_' arguments must be configured.",
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.AtLeast(1),
+ },
+ },
+ "rotation_hours": schema.Int64Attribute{
+ Description: "Number of hours to add to the base timestamp to configure the rotation timestamp. " +
+ "When the current time has passed the rotation timestamp, the resource will trigger recreation. " +
+ "At least one of the 'rotation_' arguments must be configured.",
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.AtLeast(1),
+ },
+ },
+ "rotation_minutes": schema.Int64Attribute{
+ Description: "Number of minutes to add to the base timestamp to configure the rotation timestamp. " +
+ "When the current time has passed the rotation timestamp, the resource will trigger recreation. " +
+ "At least one of the 'rotation_' arguments must be configured.",
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.AtLeast(1),
+ },
+ },
+ "rotation_months": schema.Int64Attribute{
+ Description: "Number of months to add to the base timestamp to configure the rotation timestamp. " +
+ "When the current time has passed the rotation timestamp, the resource will trigger recreation. " +
+ "At least one of the 'rotation_' arguments must be configured.",
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.AtLeast(1),
+ },
+ },
+ "rotation_rfc3339": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "Configure the rotation timestamp with an " +
+ "[RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format of the offset timestamp. " +
+ "When the current time has passed the rotation timestamp, the resource will trigger recreation. " +
+ "At least one of the 'rotation_' arguments must be configured.",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplaceIf(
+ timemodifier.ReplaceIfOutdated,
+ "resource will be replaced if current time is past the saved time",
+ "resource will be replaced if current time is past the saved time"),
+ },
+ },
+ "rotation_years": schema.Int64Attribute{
+ Description: "Number of years to add to the base timestamp to configure the rotation timestamp. " +
+ "When the current time has passed the rotation timestamp, the resource will trigger recreation. " +
+ "At least one of the 'rotation_' arguments must be configured.",
+ Optional: true,
+ Validators: []validator.Int64{
+ int64validator.AtLeast(1),
+ },
+ },
+ "hour": schema.Int64Attribute{
+ Description: "Number hour of timestamp.",
+ Computed: true,
+ },
+ "triggers": schema.MapAttribute{
+ Description: "Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved." +
+ " These conditions recreate the resource in addition to other rotation arguments. " +
+ "See [the main provider documentation](../index.md) for more information.",
+ ElementType: types.StringType,
+ Optional: true,
+ PlanModifiers: []planmodifier.Map{
+ mapplanmodifier.RequiresReplace(),
+ },
+ },
+ "minute": schema.Int64Attribute{
+ Description: "Number minute of timestamp.",
+ Computed: true,
+ },
+ "month": schema.Int64Attribute{
+ Description: "Number month of timestamp.",
+ Computed: true,
+ },
+ "rfc3339": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "Base timestamp in " +
+ "[RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format " +
+ "(see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., " +
+ "`YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "second": schema.Int64Attribute{
+ Description: "Number second of timestamp.",
+ Computed: true,
+ },
+ "unix": schema.Int64Attribute{
+ Description: "Number of seconds since epoch time, e.g. `1581489373`.",
+ Computed: true,
+ },
+ "year": schema.Int64Attribute{
+ Description: "Number year of timestamp.",
+ Computed: true,
+ },
+ "id": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "RFC3339 format of the timestamp, e.g. `2020-02-12T06:36:13Z`.",
+ Computed: true,
+ },
+ },
+ }
+}
+
+func (t timeRotatingResource) ConfigValidators(ctx context.Context) []resource.ConfigValidator {
+ return []resource.ConfigValidator{
+ resourcevalidator.AtLeastOneOf(
+ path.MatchRoot("rotation_minutes"),
+ path.MatchRoot("rotation_hours"),
+ path.MatchRoot("rotation_days"),
+ path.MatchRoot("rotation_months"),
+ path.MatchRoot("rotation_years"),
+ path.MatchRoot("rotation_rfc3339"),
+ ),
+ }
+}
+
+func (t timeRotatingResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
+ // Plan does not need to be modified when the resource is being destroyed.
+ if req.Plan.Raw.IsNull() {
+ return
+ }
+
+ // Plan only needs modifying if the resource already exists as the purpose of
+ // the plan modifier is to show updated attribute values on CLI.
+ if req.State.Raw.IsNull() {
+ return
+ }
+
+ var state, plan timeRotatingModelV0
+
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ diags = req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ if state.RotationYears == plan.RotationYears &&
+ state.RotationMonths == plan.RotationMonths &&
+ state.RotationDays == plan.RotationDays &&
+ state.RotationHours == plan.RotationHours &&
+ state.RotationMinutes == plan.RotationMinutes &&
+ state.RotationRFC3339 == plan.RotationRFC3339 {
+ return
+ }
+
+ var RFC3339, rotationRFC3339 timetypes.RFC3339
+
+ diags = req.Plan.GetAttribute(ctx, path.Root("rfc3339"), &RFC3339)
+ resp.Diagnostics = append(resp.Diagnostics, diags...)
+
+ diags = req.Plan.GetAttribute(ctx, path.Root("rotation_rfc3339"), &rotationRFC3339)
+ resp.Diagnostics = append(resp.Diagnostics, diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ // RFC3339 and rotationRFC3339 could be unknown if there is no value set in the config as the attribute is
+ // optional and computed. If base_rfc3339 is not set in config then the previous value from
+ // state is used and propagated to the update function.
+ if RFC3339.IsUnknown() {
+ resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("rfc3339"), &RFC3339)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ }
+
+ if rotationRFC3339.IsUnknown() {
+ resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("rotation_rfc3339"), &rotationRFC3339)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ }
+
+ timestamp, diags := RFC3339.ValueRFC3339Time()
+
+ resp.Diagnostics.Append(diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ resp.Diagnostics.Append(setRotationValues(&plan, timestamp)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ diags = resp.Plan.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeRotatingResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ id := req.ID
+ var state timeRotatingModelV0
+ var err error
+
+ idParts := strings.Split(id, ",")
+
+ if len(idParts) != 2 && len(idParts) != 6 {
+ resp.Diagnostics.AddError(
+ "Unexpected Format of ID",
+ fmt.Sprintf("Unexpected format of ID (%q), expected BASETIMESTAMP,YEARS,MONTHS,DAYS,HOURS,MINUTES or BASETIMESTAMP,ROTATIONTIMESTAMP", id))
+
+ return
+ }
+
+ if len(idParts) == 2 {
+ if idParts[0] == "" || idParts[1] == "" {
+ resp.Diagnostics.AddError(
+ "Unexpected Format of ID",
+ fmt.Sprintf("Unexpected format of ID (%q), expected BASETIMESTAMP,ROTATIONTIMESTAMP", id))
+ return
+ }
+
+ state, err = parseTwoPartId(idParts)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time rotating error",
+ "The timestamp that was supplied could not be parsed as RFC3339.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ } else {
+ if idParts[0] == "" || (idParts[1] == "" && idParts[2] == "" && idParts[3] == "" && idParts[4] == "" && idParts[5] == "") {
+ resp.Diagnostics.AddError(
+ "Unexpected Format of ID",
+ fmt.Sprintf("Unexpected format of ID (%q), expected BASETIMESTAMP,YEARS,MONTHS,DAYS,HOURS,MINUTES where at least one rotation value is non-empty", id))
+
+ return
+ }
+ state, err = parseMultiplePartId(idParts)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time rotating error",
+ "The parameter that was supplied could not be parsed.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+ }
+
+ state.Triggers = types.MapValueMust(types.StringType, map[string]attr.Value{})
+
+ diags := resp.State.Set(ctx, state)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeRotatingResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan timeRotatingModelV0
+
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ timestamp := time.Now().UTC()
+
+ if plan.RFC3339.ValueString() != "" {
+ rfc3339, diags := plan.RFC3339.ValueRFC3339Time()
+
+ resp.Diagnostics.Append(diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ timestamp = rfc3339
+ }
+
+ resp.Diagnostics.Append(setRotationValues(&plan, timestamp)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeRotatingResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var state timeRotatingModelV0
+
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ if !state.RotationRFC3339.IsNull() && state.RotationRFC3339.ValueString() != "" {
+ now := time.Now().UTC()
+ rotationTimestamp, diags := state.RotationRFC3339.ValueRFC3339Time()
+
+ resp.Diagnostics.Append(diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ if now.After(rotationTimestamp) {
+ log.Printf("[INFO] Expiration timestamp (%s) is after current timestamp (%s), removing from state", state.RotationRFC3339.ValueString(), now.Format(time.RFC3339))
+ resp.State.RemoveResource(ctx)
+ return
+ }
+ }
+
+}
+
+func (t timeRotatingResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var plan, state timeRotatingModelV0
+
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ diags = req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ if state.RotationYears == plan.RotationYears &&
+ state.RotationMonths == plan.RotationMonths &&
+ state.RotationDays == plan.RotationDays &&
+ state.RotationHours == plan.RotationHours &&
+ state.RotationMinutes == plan.RotationMinutes &&
+ state.RotationRFC3339 == plan.RotationRFC3339 {
+ return
+ }
+
+ timestamp, diags := plan.ID.ValueRFC3339Time()
+
+ resp.Diagnostics.Append(diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ resp.Diagnostics.Append(setRotationValues(&plan, timestamp)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ diags = resp.State.Set(ctx, plan)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeRotatingResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
+
+}
+
+type timeRotatingModelV0 struct {
+ Day types.Int64 `tfsdk:"day"`
+ RotationDays types.Int64 `tfsdk:"rotation_days"`
+ RotationHours types.Int64 `tfsdk:"rotation_hours"`
+ RotationMinutes types.Int64 `tfsdk:"rotation_minutes"`
+ RotationMonths types.Int64 `tfsdk:"rotation_months"`
+ RotationRFC3339 timetypes.RFC3339 `tfsdk:"rotation_rfc3339"`
+ RotationYears types.Int64 `tfsdk:"rotation_years"`
+ Hour types.Int64 `tfsdk:"hour"`
+ Triggers types.Map `tfsdk:"triggers"`
+ Minute types.Int64 `tfsdk:"minute"`
+ Month types.Int64 `tfsdk:"month"`
+ RFC3339 timetypes.RFC3339 `tfsdk:"rfc3339"`
+ Second types.Int64 `tfsdk:"second"`
+ Unix types.Int64 `tfsdk:"unix"`
+ Year types.Int64 `tfsdk:"year"`
+ ID timetypes.RFC3339 `tfsdk:"id"`
+}
+
+func setRotationValues(plan *timeRotatingModelV0, timestamp time.Time) diag.Diagnostics {
+ var diags diag.Diagnostics
+ var rotationTimestamp time.Time
+
+ if plan.RotationDays.ValueInt64() != 0 {
+ rotationTimestamp = timestamp.AddDate(0, 0, int(plan.RotationDays.ValueInt64()))
+ }
+
+ if plan.RotationHours.ValueInt64() != 0 {
+ hours := time.Duration(plan.RotationHours.ValueInt64()) * time.Hour
+ rotationTimestamp = timestamp.Add(hours)
+ }
+
+ if plan.RotationMinutes.ValueInt64() != 0 {
+ minutes := time.Duration(plan.RotationMinutes.ValueInt64()) * time.Minute
+ rotationTimestamp = timestamp.Add(minutes)
+ }
+
+ if plan.RotationMonths.ValueInt64() != 0 {
+ rotationTimestamp = timestamp.AddDate(0, int(plan.RotationMonths.ValueInt64()), 0)
+ }
+
+ if plan.RotationRFC3339.ValueString() != "" {
+ rotationTimestamp, diags = plan.RotationRFC3339.ValueRFC3339Time()
+ }
+
+ if plan.RotationYears.ValueInt64() != 0 {
+ rotationTimestamp = timestamp.AddDate(int(plan.RotationYears.ValueInt64()), 0, 0)
+ }
+
+ plan.RotationRFC3339 = timetypes.NewRFC3339TimeValue(rotationTimestamp)
+ plan.Year = types.Int64Value(int64(rotationTimestamp.Year()))
+ plan.Month = types.Int64Value(int64(rotationTimestamp.Month()))
+ plan.Day = types.Int64Value(int64(rotationTimestamp.Day()))
+ plan.Hour = types.Int64Value(int64(rotationTimestamp.Hour()))
+ plan.Minute = types.Int64Value(int64(rotationTimestamp.Minute()))
+ plan.Second = types.Int64Value(int64(rotationTimestamp.Second()))
+ plan.RFC3339 = timetypes.NewRFC3339TimeValue(timestamp)
+ plan.Unix = types.Int64Value(rotationTimestamp.Unix())
+ plan.ID = timetypes.NewRFC3339TimeValue(timestamp)
+
+ return diags
+}
+
+func parseTwoPartId(idParts []string) (timeRotatingModelV0, error) {
+
+ baseRfc3339 := idParts[0]
+ rotationRfc3339 := idParts[1]
+
+ timestamp, err := time.Parse(time.RFC3339, baseRfc3339)
+ if err != nil {
+ return timeRotatingModelV0{}, err
+ }
+
+ rotationTimestamp, err := time.Parse(time.RFC3339, rotationRfc3339)
+ if err != nil {
+ return timeRotatingModelV0{}, err
+ }
+
+ return timeRotatingModelV0{
+ Year: types.Int64Value(int64(rotationTimestamp.Year())),
+ Month: types.Int64Value(int64(rotationTimestamp.Month())),
+ Day: types.Int64Value(int64(rotationTimestamp.Day())),
+ Hour: types.Int64Value(int64(rotationTimestamp.Hour())),
+ Minute: types.Int64Value(int64(rotationTimestamp.Minute())),
+ Second: types.Int64Value(int64(rotationTimestamp.Second())),
+ RotationRFC3339: timetypes.NewRFC3339TimeValue(rotationTimestamp),
+ RotationYears: types.Int64Null(),
+ RotationMonths: types.Int64Null(),
+ RotationDays: types.Int64Null(),
+ RotationHours: types.Int64Null(),
+ RotationMinutes: types.Int64Null(),
+ RFC3339: timetypes.NewRFC3339TimeValue(timestamp),
+ Unix: types.Int64Value(rotationTimestamp.Unix()),
+ ID: timetypes.NewRFC3339TimeValue(timestamp),
+ }, nil
+}
+
+func parseMultiplePartId(idParts []string) (timeRotatingModelV0, error) {
+ baseRfc3339 := idParts[0]
+
+ rotationYears, err := rotationToInt64(idParts[1])
+ if err != nil {
+ return timeRotatingModelV0{}, err
+ }
+
+ rotationMonths, err := rotationToInt64(idParts[2])
+ if err != nil {
+ return timeRotatingModelV0{}, err
+ }
+
+ rotationDays, err := rotationToInt64(idParts[3])
+ if err != nil {
+ return timeRotatingModelV0{}, err
+ }
+
+ rotationHours, err := rotationToInt64(idParts[4])
+ if err != nil {
+ return timeRotatingModelV0{}, err
+ }
+
+ rotationMinutes, err := rotationToInt64(idParts[5])
+ if err != nil {
+ return timeRotatingModelV0{}, err
+ }
+
+ timestamp, err := time.Parse(time.RFC3339, baseRfc3339)
+ if err != nil {
+ return timeRotatingModelV0{}, err
+ }
+
+ var rotationTimestamp time.Time
+
+ if !rotationDays.IsNull() && rotationDays.ValueInt64() > 0 {
+ rotationTimestamp = timestamp.AddDate(0, 0, int(rotationDays.ValueInt64()))
+ }
+
+ if !rotationHours.IsNull() && rotationHours.ValueInt64() > 0 {
+ hours := time.Duration(rotationHours.ValueInt64()) * time.Hour
+ rotationTimestamp = timestamp.Add(hours)
+ }
+
+ if !rotationMinutes.IsNull() && rotationMinutes.ValueInt64() > 0 {
+ minutes := time.Duration(rotationMinutes.ValueInt64()) * time.Minute
+ rotationTimestamp = timestamp.Add(minutes)
+ }
+
+ if !rotationMonths.IsNull() && rotationMonths.ValueInt64() > 0 {
+ rotationTimestamp = timestamp.AddDate(0, int(rotationMonths.ValueInt64()), 0)
+ }
+
+ if !rotationYears.IsNull() && rotationYears.ValueInt64() > 0 {
+ rotationTimestamp = timestamp.AddDate(int(rotationYears.ValueInt64()), 0, 0)
+ }
+
+ state := timeRotatingModelV0{
+ Year: types.Int64Value(int64(rotationTimestamp.Year())),
+ Month: types.Int64Value(int64(rotationTimestamp.Month())),
+ Day: types.Int64Value(int64(rotationTimestamp.Day())),
+ Hour: types.Int64Value(int64(rotationTimestamp.Hour())),
+ Minute: types.Int64Value(int64(rotationTimestamp.Minute())),
+ Second: types.Int64Value(int64(rotationTimestamp.Second())),
+ RotationRFC3339: timetypes.NewRFC3339TimeValue(rotationTimestamp),
+ RotationYears: rotationYears,
+ RotationMonths: rotationMonths,
+ RotationDays: rotationDays,
+ RotationHours: rotationHours,
+ RotationMinutes: rotationMinutes,
+ RFC3339: timetypes.NewRFC3339TimeValue(timestamp),
+ Unix: types.Int64Value(rotationTimestamp.Unix()),
+ ID: timetypes.NewRFC3339TimeValue(timestamp),
+ }
+
+ return state, nil
+}
+
+func rotationToInt64(rotationStr string) (types.Int64, error) {
+ rotation := types.Int64Null()
+
+ if rotationStr != "" {
+ offsetInt, err := strconv.ParseInt(rotationStr, 10, 64)
+ if err != nil {
+ return rotation, fmt.Errorf("could not parse rotation (%q) as int: %w", rotationStr, err)
+ }
+
+ rotation = types.Int64Value(offsetInt)
+ }
+
+ return rotation, nil
+}
diff --git a/v0.10.0/internal/provider/resource_time_rotating_test.go b/v0.10.0/internal/provider/resource_time_rotating_test.go
new file mode 100644
index 0000000..f1eae12
--- /dev/null
+++ b/v0.10.0/internal/provider/resource_time_rotating_test.go
@@ -0,0 +1,590 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "fmt"
+ "regexp"
+ "testing"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+ "github.com/hashicorp/terraform-plugin-testing/terraform"
+)
+
+func TestAccTimeRotating_Triggers(t *testing.T) {
+ resourceName := "time_rotating.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingTriggers1("key1", "value1"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "triggers.%", "1"),
+ resource.TestCheckResourceAttr(resourceName, "triggers.key1", "value1"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_days", "1"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rotation_rfc3339"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ testSleep(1),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeRotatingImportStateIdFunc(),
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"triggers"},
+ },
+ {
+ Config: testAccConfigTimeRotatingTriggers1("key1", "value1updated"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "triggers.%", "1"),
+ resource.TestCheckResourceAttr(resourceName, "triggers.key1", "value1updated"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_days", "1"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rotation_rfc3339"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationDays_basic(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationDays(timestamp.Format(time.RFC3339), 7),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_days", "7"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(0, 0, 7).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeRotatingImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationDays_expired(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC().AddDate(0, 0, -2)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationDays(timestamp.Format(time.RFC3339), 1),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_days", "1"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(0, 0, 1).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationHours_basic(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationHours(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_hours", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.Add(3*time.Hour).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeRotatingImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationHours_expired(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC().Add(-2 * time.Hour)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationHours(timestamp.Format(time.RFC3339), 1),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_hours", "1"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.Add(1*time.Hour).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationMinutes_basic(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationMinutes(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_minutes", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.Add(3*time.Minute).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeRotatingImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationMinutes_expired(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC().Add(-2 * time.Minute)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationMinutes(timestamp.Format(time.RFC3339), 1),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_minutes", "1"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.Add(1*time.Minute).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationMonths_basic(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationMonths(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_months", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(0, 3, 0).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeRotatingImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationMonths_expired(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC().AddDate(0, -2, 0)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationMonths(timestamp.Format(time.RFC3339), 1),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_months", "1"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(0, 1, 0).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationRfc3339_basic(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC()
+ rotationTimestamp := time.Now().UTC().AddDate(0, 0, 7)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationRfc3339(timestamp.Format(time.RFC3339), rotationTimestamp.Format(time.RFC3339)),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", rotationTimestamp.Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeRotatingImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationRfc3339_expired(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC().AddDate(0, 0, -2)
+ rotationTimestamp := time.Now().UTC().AddDate(0, 0, -1)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationRfc3339(timestamp.Format(time.RFC3339), rotationTimestamp.Format(time.RFC3339)),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", rotationTimestamp.Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationYears_basic(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationYears(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_years", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(3, 0, 0).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateIdFunc: testAccTimeRotatingImportStateIdFunc(),
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationYears_expired(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC().AddDate(-2, 0, 0)
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationYears(timestamp.Format(time.RFC3339), 1),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_years", "1"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(1, 0, 0).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_RotationDays_ToRotationMonths(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeRotatingRotationDays(timestamp.Format(time.RFC3339), 7),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_days", "7"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(0, 0, 7).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ Config: testAccConfigTimeRotatingRotationMonths(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_months", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(0, 3, 0).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_years"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeRotation_Upgrade(t *testing.T) {
+ resourceName := "time_rotating.test"
+ timestamp := time.Now().UTC()
+ expiredTimestamp := time.Now().UTC().AddDate(-2, 0, 0)
+
+ resource.Test(t, resource.TestCase{
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ ExternalProviders: providerVersion080(),
+ Config: testAccConfigTimeRotatingRotationYears(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_years", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(3, 0, 0).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ Config: testAccConfigTimeRotatingRotationYears(timestamp.Format(time.RFC3339), 3),
+ PlanOnly: true,
+ },
+ {
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ Config: testAccConfigTimeRotatingRotationYears(timestamp.Format(time.RFC3339), 3),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "rotation_years", "3"),
+ resource.TestCheckResourceAttr(resourceName, "rotation_rfc3339", timestamp.AddDate(3, 0, 0).Format(time.RFC3339)),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_months"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_days"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_hours"),
+ resource.TestCheckNoResourceAttr(resourceName, "rotation_minutes"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ ),
+ },
+ {
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ Config: testAccConfigTimeRotatingRotationYears(expiredTimestamp.Format(time.RFC3339), 3),
+ PlanOnly: true,
+ ExpectNonEmptyPlan: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeRotating_Validators(t *testing.T) {
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: fmt.Sprintf(`resource "time_rotating" "test" {
+ rfc3339 = %q
+ }`, timestamp.Format(time.RFC3339)),
+ ExpectError: regexp.MustCompile(`.*Error: Missing Attribute Configuration`),
+ },
+ {
+ Config: testAccConfigTimeRotatingRotationMinutes(timestamp.Format(time.RFC822), 1),
+ ExpectError: regexp.MustCompile(`.*Invalid RFC3339 String Value`),
+ },
+ {
+ Config: testAccConfigTimeRotatingRotationMinutes(timestamp.Format(time.RFC3339), 0),
+ ExpectError: regexp.MustCompile(`.*must be at least 1`),
+ },
+ },
+ })
+}
+
+func testAccTimeRotatingImportStateIdFunc() resource.ImportStateIdFunc {
+ return func(s *terraform.State) (string, error) {
+ resourceName := "time_rotating.test"
+ rs, ok := s.RootModule().Resources[resourceName]
+ if !ok {
+ return "", fmt.Errorf("Not found: %s", resourceName)
+ }
+
+ rotationYears := rs.Primary.Attributes["rotation_years"]
+ rotationMonths := rs.Primary.Attributes["rotation_months"]
+ rotationDays := rs.Primary.Attributes["rotation_days"]
+ rotationHours := rs.Primary.Attributes["rotation_hours"]
+ rotationMinutes := rs.Primary.Attributes["rotation_minutes"]
+
+ if rotationYears != "" || rotationMonths != "" || rotationDays != "" || rotationHours != "" || rotationMinutes != "" {
+ return fmt.Sprintf("%s,%s,%s,%s,%s,%s", rs.Primary.ID, rotationYears, rotationMonths, rotationDays, rotationHours, rotationMinutes), nil
+ }
+
+ return fmt.Sprintf("%s,%s", rs.Primary.ID, rs.Primary.Attributes["rotation_rfc3339"]), nil
+ }
+}
+
+func testAccConfigTimeRotatingTriggers1(keeperKey1 string, keeperKey2 string) string {
+ return fmt.Sprintf(`
+resource "time_rotating" "test" {
+ triggers = {
+ %[1]q = %[2]q
+ }
+ rotation_days = 1
+}
+`, keeperKey1, keeperKey2)
+}
+
+func testAccConfigTimeRotatingRotationDays(rfc3339 string, rotationDays int) string {
+ return fmt.Sprintf(`
+resource "time_rotating" "test" {
+ rotation_days = %[2]d
+ rfc3339 = %[1]q
+}
+`, rfc3339, rotationDays)
+}
+
+func testAccConfigTimeRotatingRotationHours(rfc3339 string, rotationHours int) string {
+ return fmt.Sprintf(`
+resource "time_rotating" "test" {
+ rotation_hours = %[2]d
+ rfc3339 = %[1]q
+}
+`, rfc3339, rotationHours)
+}
+
+func testAccConfigTimeRotatingRotationMinutes(rfc3339 string, rotationMinutes int) string {
+ return fmt.Sprintf(`
+resource "time_rotating" "test" {
+ rotation_minutes = %[2]d
+ rfc3339 = %[1]q
+}
+`, rfc3339, rotationMinutes)
+}
+
+func testAccConfigTimeRotatingRotationMonths(rfc3339 string, rotationMonths int) string {
+ return fmt.Sprintf(`
+resource "time_rotating" "test" {
+ rotation_months = %[2]d
+ rfc3339 = %[1]q
+}
+`, rfc3339, rotationMonths)
+}
+
+func testAccConfigTimeRotatingRotationYears(rfc3339 string, rotationYears int) string {
+ return fmt.Sprintf(`
+resource "time_rotating" "test" {
+ rotation_years = %[2]d
+ rfc3339 = %[1]q
+}
+`, rfc3339, rotationYears)
+}
+
+func testAccConfigTimeRotatingRotationRfc3339(rfc3339 string, rotationRfc3339 string) string {
+ return fmt.Sprintf(`
+resource "time_rotating" "test" {
+ rotation_rfc3339 = %[2]q
+ rfc3339 = %[1]q
+}
+`, rfc3339, rotationRfc3339)
+}
diff --git a/v0.10.0/internal/provider/resource_time_sleep.go b/v0.10.0/internal/provider/resource_time_sleep.go
new file mode 100644
index 0000000..785edc7
--- /dev/null
+++ b/v0.10.0/internal/provider/resource_time_sleep.go
@@ -0,0 +1,233 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "context"
+ "fmt"
+ "regexp"
+ "strings"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/schema/validator"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+
+ "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+)
+
+var (
+ _ resource.Resource = (*timeSleepResource)(nil)
+ _ resource.ResourceWithImportState = (*timeSleepResource)(nil)
+)
+
+func NewTimeSleepResource() resource.Resource {
+ return &timeSleepResource{}
+}
+
+type timeSleepResource struct{}
+
+func (t timeSleepResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_sleep"
+}
+
+func (t timeSleepResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Manages a resource that delays creation and/or destruction, typically for further resources. " +
+ "This prevents cross-platform compatibility and destroy-time issues with using " +
+ "the [`local-exec` provisioner](https://www.terraform.io/docs/provisioners/local-exec.html).",
+ Attributes: map[string]schema.Attribute{
+ "create_duration": schema.StringAttribute{
+ Description: "[Time duration](https://golang.org/pkg/time/#ParseDuration) to delay resource creation. " +
+ "For example, `30s` for 30 seconds or `5m` for 5 minutes. Updating this value by itself will not trigger a delay.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.AtLeastOneOf(path.MatchRoot("destroy_duration")),
+ stringvalidator.RegexMatches(regexp.MustCompile(`^[0-9]+(\.[0-9]+)?(ms|s|m|h)$`),
+ "must be a number immediately followed by ms (milliseconds), s (seconds), m (minutes), or h (hours). For example, \"30s\" for 30 seconds."),
+ },
+ },
+ "destroy_duration": schema.StringAttribute{
+ Description: "[Time duration](https://golang.org/pkg/time/#ParseDuration) to delay resource destroy. " +
+ "For example, `30s` for 30 seconds or `5m` for 5 minutes. Updating this value by itself will not trigger a delay. " +
+ "This value or any updates to it must be successfully applied into the Terraform state before destroying this resource to take effect.",
+ Optional: true,
+ Validators: []validator.String{
+ stringvalidator.AtLeastOneOf(path.MatchRoot("create_duration")),
+ stringvalidator.RegexMatches(regexp.MustCompile(`^[0-9]+(\.[0-9]+)?(ms|s|m|h)$`),
+ "must be a number immediately followed by ms (milliseconds), s (seconds), m (minutes), or h (hours). For example, \"30s\" for 30 seconds."),
+ },
+ },
+ "triggers": schema.MapAttribute{
+ Description: "(Optional) Arbitrary map of values that, when changed, will run any creation or destroy delays again. " +
+ "See [the main provider documentation](../index.md) for more information.",
+ ElementType: types.StringType,
+ Optional: true,
+ PlanModifiers: []planmodifier.Map{
+ mapplanmodifier.RequiresReplace(),
+ },
+ },
+ "id": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ },
+ }
+}
+
+func (t timeSleepResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ id := req.ID
+
+ idParts := strings.Split(id, ",")
+
+ if len(idParts) != 2 || (idParts[0] == "" && idParts[1] == "") {
+ resp.Diagnostics.AddError(
+ "Unexpected Format of ID",
+ fmt.Sprintf("Unexpected format of ID (%q), expected CREATEDURATION,DESTROYDURATION where at least one value is non-empty", id))
+
+ return
+ }
+
+ state := timeSleepModelV0{
+ CreateDuration: types.StringNull(),
+ DestroyDuration: types.StringNull(),
+ ID: timetypes.NewRFC3339TimeValue(time.Now().UTC()),
+ }
+
+ if idParts[0] != "" {
+ _, err := time.ParseDuration(idParts[0])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time sleep error",
+ "The create_duration cannot be parsed\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+ state.CreateDuration = types.StringValue(idParts[0])
+ }
+
+ if idParts[1] != "" {
+ _, err := time.ParseDuration(idParts[1])
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time sleep error",
+ "The create_duration cannot be parsed\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+ state.DestroyDuration = types.StringValue(idParts[1])
+ }
+
+ state.Triggers = types.MapValueMust(types.StringType, map[string]attr.Value{})
+
+ diags := resp.State.Set(ctx, state)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeSleepResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan timeSleepModelV0
+
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ if plan.CreateDuration.ValueString() != "" {
+ duration, err := time.ParseDuration(plan.CreateDuration.ValueString())
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Create time sleep error",
+ "The create_duration cannot be parsed\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ select {
+ case <-ctx.Done():
+ resp.Diagnostics.AddError(
+ "Create time sleep error",
+ fmt.Sprintf("Original Error: %s", ctx.Err()),
+ )
+ return
+ case <-time.After(duration):
+ }
+ }
+
+ state := timeSleepModelV0{
+ CreateDuration: plan.CreateDuration,
+ DestroyDuration: plan.DestroyDuration,
+ Triggers: plan.Triggers,
+ ID: timetypes.NewRFC3339TimeValue(time.Now().UTC()),
+ }
+ diags = resp.State.Set(ctx, state)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeSleepResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+
+}
+
+func (t timeSleepResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var data timeSleepModelV0
+
+ // Read Terraform plan data into the model
+ resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+
+ // Save updated data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (t timeSleepResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var state timeSleepModelV0
+
+ diags := req.State.Get(ctx, &state)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ if state.DestroyDuration.ValueString() != "" {
+ duration, err := time.ParseDuration(state.DestroyDuration.ValueString())
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Delete time sleep error",
+ "The create_duration cannot be parsed\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ select {
+ case <-ctx.Done():
+ resp.Diagnostics.AddError(
+ "Delete time sleep error",
+ fmt.Sprintf("Original Error: %s", ctx.Err()),
+ )
+ return
+ case <-time.After(duration):
+ }
+ }
+}
+
+type timeSleepModelV0 struct {
+ CreateDuration types.String `tfsdk:"create_duration"`
+ DestroyDuration types.String `tfsdk:"destroy_duration"`
+ Triggers types.Map `tfsdk:"triggers"`
+ ID timetypes.RFC3339 `tfsdk:"id"`
+}
diff --git a/v0.10.0/internal/provider/resource_time_sleep_test.go b/v0.10.0/internal/provider/resource_time_sleep_test.go
new file mode 100644
index 0000000..4908c21
--- /dev/null
+++ b/v0.10.0/internal/provider/resource_time_sleep_test.go
@@ -0,0 +1,369 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "context"
+ "fmt"
+ "regexp"
+ "testing"
+ "time"
+
+ r "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/tfsdk"
+ "github.com/hashicorp/terraform-plugin-go/tftypes"
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+// Since the acceptance testing framework can introduce uncontrollable time delays,
+// verify that sleeping works as expected via unit testing.
+func TestResourceTimeSleepCreate(t *testing.T) {
+ durationStr := "1s"
+ expectedDuration, err := time.ParseDuration("1s")
+
+ if err != nil {
+ t.Fatalf("unable to parse test duration: %s", err)
+ }
+
+ sleepResource := NewTimeSleepResource()
+
+ m := map[string]tftypes.Value{
+ "create_duration": tftypes.NewValue(tftypes.String, durationStr),
+ "destroy_duration": tftypes.NewValue(tftypes.String, nil),
+ "id": tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
+ "triggers": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, nil),
+ }
+ config := tftypes.NewValue(tftypes.Object{
+ AttributeTypes: map[string]tftypes.Type{
+ "create_duration": tftypes.String,
+ "destroy_duration": tftypes.String,
+ "id": tftypes.String,
+ "triggers": tftypes.Map{ElementType: tftypes.String},
+ },
+ OptionalAttributes: map[string]struct{}{
+ "create_duration": {},
+ "destroy_duration": {},
+ "triggers": {},
+ },
+ }, m)
+ plan := tftypes.NewValue(tftypes.Object{
+ AttributeTypes: map[string]tftypes.Type{
+ "create_duration": tftypes.String,
+ "destroy_duration": tftypes.String,
+ "id": tftypes.String,
+ "triggers": tftypes.Map{ElementType: tftypes.String},
+ },
+ OptionalAttributes: map[string]struct{}{
+ "create_duration": {},
+ "destroy_duration": {},
+ "triggers": {},
+ },
+ }, m)
+
+ schemaResponse := r.SchemaResponse{}
+ sleepResource.Schema(context.Background(), r.SchemaRequest{}, &schemaResponse)
+
+ req := r.CreateRequest{
+ Config: tfsdk.Config{
+ Raw: config,
+ Schema: schemaResponse.Schema,
+ },
+ Plan: tfsdk.Plan{
+ Raw: plan,
+ Schema: schemaResponse.Schema,
+ },
+ ProviderMeta: tfsdk.Config{},
+ }
+
+ resp := r.CreateResponse{
+ State: tfsdk.State{
+ Schema: schemaResponse.Schema,
+ },
+ Diagnostics: nil,
+ }
+
+ start := time.Now()
+ sleepResource.Create(context.Background(), req, &resp)
+ end := time.Now()
+ elapsed := end.Sub(start)
+
+ if elapsed < expectedDuration {
+ t.Errorf("did not sleep long enough, expected duration: %d got: %d", expectedDuration, elapsed)
+ }
+}
+
+// Since the acceptance testing framework can introduce uncontrollable time delays,
+// verify that sleeping works as expected via unit testing.
+func TestResourceTimeSleepDelete(t *testing.T) {
+ durationStr := "1s"
+ expectedDuration, err := time.ParseDuration("1s")
+
+ if err != nil {
+ t.Fatalf("unable to parse test duration: %s", err)
+ }
+
+ sleepResource := NewTimeSleepResource()
+
+ m := map[string]tftypes.Value{
+ "create_duration": tftypes.NewValue(tftypes.String, nil),
+ "destroy_duration": tftypes.NewValue(tftypes.String, durationStr),
+ "id": tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
+ "triggers": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, nil),
+ }
+
+ config := tftypes.NewValue(tftypes.Object{
+ AttributeTypes: map[string]tftypes.Type{
+ "create_duration": tftypes.String,
+ "destroy_duration": tftypes.String,
+ "id": tftypes.String,
+ "triggers": tftypes.Map{ElementType: tftypes.String},
+ },
+ OptionalAttributes: map[string]struct{}{
+ "create_duration": {},
+ "destroy_duration": {},
+ "triggers": {},
+ },
+ }, m)
+
+ schemaResponse := r.SchemaResponse{}
+ sleepResource.Schema(context.Background(), r.SchemaRequest{}, &schemaResponse)
+
+ req := r.DeleteRequest{
+ State: tfsdk.State{
+ Raw: config,
+ Schema: schemaResponse.Schema,
+ },
+ ProviderMeta: tfsdk.Config{},
+ }
+
+ resp := r.DeleteResponse{
+ State: tfsdk.State{
+ Schema: schemaResponse.Schema,
+ },
+ Diagnostics: nil,
+ }
+
+ start := time.Now()
+ sleepResource.Delete(context.Background(), req, &resp)
+ end := time.Now()
+ elapsed := end.Sub(start)
+
+ if elapsed < expectedDuration {
+ t.Errorf("did not sleep long enough, expected duration: %d got: %d", expectedDuration, elapsed)
+ }
+}
+
+func TestAccTimeSleep_CreateDuration(t *testing.T) {
+ var time1, time2 string
+ resourceName := "time_sleep.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeSleepCreateDuration("1ms"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "create_duration", "1ms"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ testExtractResourceAttr(resourceName, "id", &time1),
+ ),
+ },
+ // This test may work in local execution but typically does not work in CI because of its reliance
+ // on the current time stamp in the ID. We will also need to revisit this test later once TF core allows
+ // multiple parameters in Import
+ //{
+ // ResourceName: resourceName,
+ // ImportState: true,
+ // ImportStateIdFunc: testAccTimeSleepImportStateIdFunc(resourceName),
+ // ImportStateVerify: true,
+ //},
+ {
+ Config: testAccConfigTimeSleepCreateDuration("2ms"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "create_duration", "2ms"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ testExtractResourceAttr(resourceName, "id", &time2),
+ testCheckAttributeValuesSame(&time1, &time2),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeSleep_DestroyDuration(t *testing.T) {
+ var time1, time2 string
+ resourceName := "time_sleep.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeSleepDestroyDuration("1ms"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "destroy_duration", "1ms"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ testExtractResourceAttr(resourceName, "id", &time1),
+ ),
+ },
+ // This test may work in local execution but typically does not work in CI because of its reliance
+ // on the current time stamp in the ID. We will also need to revisit this test later once TF core allows
+ // multiple parameters in Import
+ //{
+ // ResourceName: resourceName,
+ // ImportState: true,
+ // ImportStateIdFunc: testAccTimeSleepImportStateIdFunc(resourceName),
+ // ImportStateVerify: true,
+ //},
+ {
+ Config: testAccConfigTimeSleepDestroyDuration("2ms"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "destroy_duration", "2ms"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ testExtractResourceAttr(resourceName, "id", &time2),
+ testCheckAttributeValuesSame(&time1, &time2),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeSleep_Triggers(t *testing.T) {
+ var time1, time2 string
+ resourceName := "time_sleep.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeSleepTriggers1("key1", "value1"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "triggers.%", "1"),
+ resource.TestCheckResourceAttr(resourceName, "triggers.key1", "value1"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ resource.TestCheckResourceAttrSet(resourceName, "create_duration"),
+ testExtractResourceAttr(resourceName, "id", &time1),
+ ),
+ },
+ // This test may work in local execution but typically does not work in CI because of its reliance
+ // on the current time stamp in the ID. We will also need to revisit this test later once TF core allows
+ // multiple parameters in Import
+ //{
+ // ResourceName: resourceName,
+ // ImportState: true,
+ // ImportStateIdFunc: testAccTimeSleepImportStateIdFunc(resourceName),
+ // ImportStateVerify: true,
+ // ImportStateVerifyIgnore: []string{"triggers"},
+ //},
+ {
+ Config: testAccConfigTimeSleepTriggers1("key1", "value1updated"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "triggers.%", "1"),
+ resource.TestCheckResourceAttr(resourceName, "triggers.key1", "value1updated"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ resource.TestCheckResourceAttrSet(resourceName, "create_duration"),
+ testExtractResourceAttr(resourceName, "id", &time2),
+ testCheckAttributeValuesDiffer(&time1, &time2),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeSleep_Upgrade(t *testing.T) {
+ resourceName := "time_sleep.test"
+
+ resource.Test(t, resource.TestCase{
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ ExternalProviders: providerVersion080(),
+ Config: testAccConfigTimeSleepCreateDuration("1ms"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "create_duration", "1ms"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ ),
+ },
+ {
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ Config: testAccConfigTimeSleepCreateDuration("1ms"),
+ PlanOnly: true,
+ },
+ {
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ Config: testAccConfigTimeSleepCreateDuration("1ms"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "create_duration", "1ms"),
+ resource.TestCheckResourceAttrSet(resourceName, "id"),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeSleep_Validators(t *testing.T) {
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: fmt.Sprintf(`resource "time_sleep" "test" {
+ triggers = {
+ %[1]q = %[2]q
+ }
+ }`, "key1", "value1"),
+ ExpectError: regexp.MustCompile(`.*Error: Invalid Attribute Combination`),
+ },
+ {
+ Config: testAccConfigTimeSleepCreateDuration("1"),
+ ExpectError: regexp.MustCompile(`.*Error: Invalid Attribute Value Match`),
+ },
+ },
+ })
+}
+
+//func testAccTimeSleepImportStateIdFunc(resourceName string) resource.ImportStateIdFunc {
+// return func(s *terraform.State) (string, error) {
+// rs, ok := s.RootModule().Resources[resourceName]
+// if !ok {
+// return "", fmt.Errorf("Not found: %s", resourceName)
+// }
+//
+// createDuration := rs.Primary.Attributes["create_duration"]
+// destroyDuration := rs.Primary.Attributes["destroy_duration"]
+//
+// return fmt.Sprintf("%s,%s", createDuration, destroyDuration), nil
+// }
+//}
+
+func testAccConfigTimeSleepCreateDuration(createDuration string) string {
+ return fmt.Sprintf(`
+resource "time_sleep" "test" {
+ create_duration = %[1]q
+}
+`, createDuration)
+}
+
+func testAccConfigTimeSleepDestroyDuration(destroyDuration string) string {
+ return fmt.Sprintf(`
+resource "time_sleep" "test" {
+ destroy_duration = %[1]q
+}
+`, destroyDuration)
+}
+
+func testAccConfigTimeSleepTriggers1(keeperKey1 string, keeperKey2 string) string {
+ return fmt.Sprintf(`
+resource "time_sleep" "test" {
+ create_duration = "1s"
+
+ triggers = {
+ %[1]q = %[2]q
+ }
+}
+`, keeperKey1, keeperKey2)
+}
diff --git a/v0.10.0/internal/provider/resource_time_static.go b/v0.10.0/internal/provider/resource_time_static.go
new file mode 100644
index 0000000..b8c8432
--- /dev/null
+++ b/v0.10.0/internal/provider/resource_time_static.go
@@ -0,0 +1,200 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+var (
+ _ resource.Resource = (*timeStaticResource)(nil)
+ _ resource.ResourceWithImportState = (*timeStaticResource)(nil)
+)
+
+func NewTimeStaticResource() resource.Resource {
+ return &timeStaticResource{}
+}
+
+type timeStaticResource struct{}
+
+func (t timeStaticResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_static"
+}
+
+func (t timeStaticResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Description: "Manages a static time resource, which keeps a locally sourced UTC timestamp stored in the Terraform state. " +
+ "This prevents perpetual differences caused by using " +
+ "the [`timestamp()` function](https://www.terraform.io/docs/configuration/functions/timestamp.html).",
+ Attributes: map[string]schema.Attribute{
+ "day": schema.Int64Attribute{
+ Description: "Number day of timestamp.",
+ Computed: true,
+ },
+ "hour": schema.Int64Attribute{
+ Description: "Number hour of timestamp.",
+ Computed: true,
+ },
+ "triggers": schema.MapAttribute{
+ Description: "Arbitrary map of values that, when changed, will trigger a new base timestamp value to be saved. " +
+ "See [the main provider documentation](../index.md) for more information.",
+ ElementType: types.StringType,
+ Optional: true,
+ PlanModifiers: []planmodifier.Map{
+ mapplanmodifier.RequiresReplace(),
+ },
+ },
+ "minute": schema.Int64Attribute{
+ Description: "Number minute of timestamp.",
+ Computed: true,
+ },
+ "month": schema.Int64Attribute{
+ Description: "Number month of timestamp.",
+ Computed: true,
+ },
+ "rfc3339": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "Base timestamp in " +
+ "[RFC3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) format " +
+ "(see [RFC3339 time string](https://tools.ietf.org/html/rfc3339#section-5.8) e.g., " +
+ "`YYYY-MM-DDTHH:MM:SSZ`). Defaults to the current time.",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.RequiresReplace(),
+ },
+ },
+ "second": schema.Int64Attribute{
+ Description: "Number second of timestamp.",
+ Computed: true,
+ },
+ "unix": schema.Int64Attribute{
+ Description: "Number of seconds since epoch time, e.g. `1581489373`.",
+ Computed: true,
+ },
+ "year": schema.Int64Attribute{
+ Description: "Number year of timestamp.",
+ Computed: true,
+ },
+ "id": schema.StringAttribute{
+ CustomType: timetypes.RFC3339Type{},
+ Description: "RFC3339 format of the offset timestamp, e.g. `2020-02-12T06:36:13Z`.",
+ Computed: true,
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ },
+ }
+}
+
+func (t timeStaticResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ timestamp, err := time.Parse(time.RFC3339, req.ID)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "Import time static error",
+ "The id that was supplied could not be parsed as RFC3339.\n\n+"+
+ fmt.Sprintf("Original Error: %s", err),
+ )
+ return
+ }
+
+ state := timeStaticModelV0{
+ Year: types.Int64Value(int64(timestamp.Year())),
+ Month: types.Int64Value(int64(timestamp.Month())),
+ Day: types.Int64Value(int64(timestamp.Day())),
+ Hour: types.Int64Value(int64(timestamp.Hour())),
+ Minute: types.Int64Value(int64(timestamp.Minute())),
+ Second: types.Int64Value(int64(timestamp.Second())),
+ RFC3339: timetypes.NewRFC3339TimeValue(timestamp),
+ Unix: types.Int64Value(timestamp.Unix()),
+ ID: timetypes.NewRFC3339TimeValue(timestamp),
+ }
+ state.Triggers = types.MapValueMust(types.StringType, map[string]attr.Value{})
+
+ diags := resp.State.Set(ctx, state)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeStaticResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var plan timeStaticModelV0
+
+ diags := req.Plan.Get(ctx, &plan)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ timestamp := time.Now().UTC()
+
+ if plan.RFC3339.ValueString() != "" {
+ rfc3339, diags := plan.RFC3339.ValueRFC3339Time()
+
+ resp.Diagnostics.Append(diags...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ timestamp = rfc3339
+ }
+
+ state := timeStaticModelV0{
+ Triggers: plan.Triggers,
+ Year: types.Int64Value(int64(timestamp.Year())),
+ Month: types.Int64Value(int64(timestamp.Month())),
+ Day: types.Int64Value(int64(timestamp.Day())),
+ Hour: types.Int64Value(int64(timestamp.Hour())),
+ Minute: types.Int64Value(int64(timestamp.Minute())),
+ Second: types.Int64Value(int64(timestamp.Second())),
+ RFC3339: timetypes.NewRFC3339TimeValue(timestamp),
+ Unix: types.Int64Value(timestamp.Unix()),
+ ID: timetypes.NewRFC3339TimeValue(timestamp),
+ }
+
+ diags = resp.State.Set(ctx, state)
+ resp.Diagnostics.Append(diags...)
+}
+
+func (t timeStaticResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+
+}
+
+func (t timeStaticResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var data timeStaticModelV0
+
+ // Read Terraform plan data into the model
+ resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+
+ // Save updated data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (t timeStaticResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+
+}
+
+type timeStaticModelV0 struct {
+ Day types.Int64 `tfsdk:"day"`
+ Hour types.Int64 `tfsdk:"hour"`
+ Triggers types.Map `tfsdk:"triggers"`
+ Minute types.Int64 `tfsdk:"minute"`
+ Month types.Int64 `tfsdk:"month"`
+ RFC3339 timetypes.RFC3339 `tfsdk:"rfc3339"`
+ Second types.Int64 `tfsdk:"second"`
+ Unix types.Int64 `tfsdk:"unix"`
+ Year types.Int64 `tfsdk:"year"`
+ ID timetypes.RFC3339 `tfsdk:"id"`
+}
diff --git a/v0.10.0/internal/provider/resource_time_static_test.go b/v0.10.0/internal/provider/resource_time_static_test.go
new file mode 100644
index 0000000..a56260b
--- /dev/null
+++ b/v0.10.0/internal/provider/resource_time_static_test.go
@@ -0,0 +1,200 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package provider
+
+import (
+ "fmt"
+ "regexp"
+ "strconv"
+ "testing"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+func TestAccTimeStatic_basic(t *testing.T) {
+ resourceName := "time_static.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeStatic(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestMatchResourceAttr(resourceName, "day", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "hour", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "minute", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "month", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "rfc3339", regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$`)),
+ resource.TestMatchResourceAttr(resourceName, "second", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "unix", regexp.MustCompile(`^\d+$`)),
+ resource.TestMatchResourceAttr(resourceName, "year", regexp.MustCompile(`^\d{4}$`)),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeStatic_Triggers(t *testing.T) {
+ var time1, time2 string
+ resourceName := "time_static.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeStaticTriggers1("key1", "value1"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "triggers.%", "1"),
+ resource.TestCheckResourceAttr(resourceName, "triggers.key1", "value1"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ testExtractResourceAttr(resourceName, "rfc3339", &time1),
+ testSleep(1),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"triggers"},
+ },
+ {
+ Config: testAccConfigTimeStaticTriggers1("key1", "value1updated"),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "triggers.%", "1"),
+ resource.TestCheckResourceAttr(resourceName, "triggers.key1", "value1updated"),
+ resource.TestCheckResourceAttrSet(resourceName, "rfc3339"),
+ testExtractResourceAttr(resourceName, "rfc3339", &time2),
+ testCheckAttributeValuesDiffer(&time1, &time2),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeStatic_Rfc3339(t *testing.T) {
+ resourceName := "time_static.test"
+ timestamp := time.Now().UTC()
+ day := strconv.Itoa(timestamp.Day())
+ hour := strconv.Itoa(timestamp.Hour())
+ minute := strconv.Itoa(timestamp.Minute())
+ month := strconv.Itoa(int(timestamp.Month()))
+ second := strconv.Itoa(timestamp.Second())
+ unix := strconv.Itoa(int(timestamp.Unix()))
+ year := strconv.Itoa(timestamp.Year())
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeStaticRfc3339(timestamp.Format(time.RFC3339)),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "day", day),
+ resource.TestCheckResourceAttr(resourceName, "hour", hour),
+ resource.TestCheckResourceAttr(resourceName, "minute", minute),
+ resource.TestCheckResourceAttr(resourceName, "month", month),
+ resource.TestCheckResourceAttr(resourceName, "rfc3339", timestamp.Format(time.RFC3339)),
+ resource.TestCheckResourceAttr(resourceName, "second", second),
+ resource.TestCheckResourceAttr(resourceName, "unix", unix),
+ resource.TestCheckResourceAttr(resourceName, "year", year),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func TestAccTimeStatic_Upgrade(t *testing.T) {
+ resourceName := "time_static.test"
+
+ resource.Test(t, resource.TestCase{
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ ExternalProviders: providerVersion080(),
+ Config: testAccConfigTimeStatic(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestMatchResourceAttr(resourceName, "day", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "hour", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "minute", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "month", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "rfc3339", regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$`)),
+ resource.TestMatchResourceAttr(resourceName, "second", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "unix", regexp.MustCompile(`^\d+$`)),
+ resource.TestMatchResourceAttr(resourceName, "year", regexp.MustCompile(`^\d{4}$`)),
+ ),
+ },
+ {
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ Config: testAccConfigTimeStatic(),
+ PlanOnly: true,
+ },
+ {
+ ExternalProviders: providerVersion080(),
+ Config: testAccConfigTimeStatic(),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestMatchResourceAttr(resourceName, "day", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "hour", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "minute", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "month", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "rfc3339", regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$`)),
+ resource.TestMatchResourceAttr(resourceName, "second", regexp.MustCompile(`^\d{1,2}$`)),
+ resource.TestMatchResourceAttr(resourceName, "unix", regexp.MustCompile(`^\d+$`)),
+ resource.TestMatchResourceAttr(resourceName, "year", regexp.MustCompile(`^\d{4}$`)),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccTimeStatic_Validators(t *testing.T) {
+ timestamp := time.Now().UTC()
+
+ resource.UnitTest(t, resource.TestCase{
+ ProtoV5ProviderFactories: protoV5ProviderFactories(),
+ CheckDestroy: nil,
+ Steps: []resource.TestStep{
+ {
+ Config: testAccConfigTimeStaticRfc3339(timestamp.Format(time.RFC850)),
+ ExpectError: regexp.MustCompile(`.*Invalid RFC3339 String Value`),
+ },
+ },
+ })
+}
+
+func testAccConfigTimeStatic() string {
+ return `
+resource "time_static" "test" {}
+`
+}
+
+func testAccConfigTimeStaticTriggers1(keeperKey1 string, keeperKey2 string) string {
+ return fmt.Sprintf(`
+resource "time_static" "test" {
+ triggers = {
+ %[1]q = %[2]q
+ }
+}
+`, keeperKey1, keeperKey2)
+}
+
+func testAccConfigTimeStaticRfc3339(rfc3339 string) string {
+ return fmt.Sprintf(`
+resource "time_static" "test" {
+ rfc3339 = %[1]q
+}
+`, rfc3339)
+}
diff --git a/v0.10.0/main.go b/v0.10.0/main.go
new file mode 100644
index 0000000..8ab2765
--- /dev/null
+++ b/v0.10.0/main.go
@@ -0,0 +1,30 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package main
+
+import (
+ "context"
+ "flag"
+ "log"
+
+ "github.com/hashicorp/terraform-provider-time/internal/provider"
+
+ "github.com/hashicorp/terraform-plugin-framework/providerserver"
+)
+
+func main() {
+ var debug bool
+
+ flag.BoolVar(&debug, "debug", false, "set to true to run the provider with support for debuggers like delve")
+ flag.Parse()
+
+ err := providerserver.Serve(context.Background(), provider.New, providerserver.ServeOpts{
+ Address: "registry.terraform.io/hashicorp/time",
+ Debug: debug,
+ ProtocolVersion: 5,
+ })
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/v0.10.0/templates/index.md.tmpl b/v0.10.0/templates/index.md.tmpl
new file mode 100644
index 0000000..8c53ebb
--- /dev/null
+++ b/v0.10.0/templates/index.md.tmpl
@@ -0,0 +1,29 @@
+---
+page_title: "Provider: Time"
+description: |-
+ The time provider is used to interact with time-based resources.
+---
+
+# Time Provider
+
+The time provider is used to interact with time-based resources. The provider itself has no configuration options.
+
+Use the navigation to the left to read about the available resources.
+
+## Resource "Triggers"
+
+Certain time resources, only perform actions during specific lifecycle actions:
+
+- `time_offset`: Saves base timestamp into Terraform state only when created.
+- `time_sleep`: Sleeps when created and/or destroyed.
+- `time_static`: Saves base timestamp into Terraform state only when created.
+
+These resources provide an optional map argument called `triggers` that can be populated with arbitrary key/value pairs. When the keys or values of this argument are updated, Terraform will re-perform the desired action, such as updating the base timestamp or sleeping again.
+
+For example:
+
+{{ tffile "examples/resources/resource_triggers.tf" }}
+
+`triggers` are *not* treated as sensitive attributes; a value used for `triggers` will be displayed in Terraform UI output as plaintext.
+
+To force a these actions to reoccur without updating `triggers`, the [`terraform taint` command](https://www.terraform.io/docs/commands/taint.html) can be used to produce the action on the next run.
diff --git a/v0.10.0/templates/resources/offset.md.tmpl b/v0.10.0/templates/resources/offset.md.tmpl
new file mode 100644
index 0000000..c52ef0b
--- /dev/null
+++ b/v0.10.0/templates/resources/offset.md.tmpl
@@ -0,0 +1,36 @@
+---
+page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
+subcategory: ""
+description: |-
+{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
+---
+
+# {{.Name}} ({{.Type}})
+
+{{ .Description | trimspace }}
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+{{ tffile "examples/resources/time_offset/resource.tf" }}
+
+### Multiple Offsets Usage
+
+{{ tffile "examples/resources/time_offset/resource_multiple_offset.tf" }}
+
+### Triggers Usage
+
+{{ tffile "examples/resources/time_offset/resource_triggers.tf" }}
+
+{{ .SchemaMarkdown | trimspace }}
+
+## Import
+
+This resource can be imported using the base UTC RFC3339 timestamp and offset years, months, days, hours, minutes, and seconds, separated by commas (`,`), e.g.
+
+{{codefile "shell" .ImportFile }}
+
+The `triggers` argument cannot be imported.
\ No newline at end of file
diff --git a/v0.10.0/templates/resources/rotating.md.tmpl b/v0.10.0/templates/resources/rotating.md.tmpl
new file mode 100644
index 0000000..e32e993
--- /dev/null
+++ b/v0.10.0/templates/resources/rotating.md.tmpl
@@ -0,0 +1,32 @@
+---
+page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
+subcategory: ""
+description: |-
+{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
+---
+
+# {{.Name}} ({{.Type}})
+
+{{ .Description | trimspace }}
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+{{ tffile "examples/resources/time_rotating/resource.tf" }}
+
+{{ .SchemaMarkdown | trimspace }}
+
+## Import
+
+This resource can be imported using the base UTC RFC3339 value and rotation years, months, days, hours, and minutes, separated by commas (`,`), e.g. for 30 days
+
+{{codefile "shell" "examples/resources/time_rotating/import_base_value.sh"}}
+
+Otherwise, to import with the rotation RFC3339 value, the base UTC RFC3339 value and rotation UTC RFC3339 value, separated by commas (`,`), e.g.
+
+{{codefile "shell" "examples/resources/time_rotating/import_rotation_value.sh"}}
+
+The `triggers` argument cannot be imported.
diff --git a/v0.10.0/templates/resources/sleep.md.tmpl b/v0.10.0/templates/resources/sleep.md.tmpl
new file mode 100644
index 0000000..3c473fd
--- /dev/null
+++ b/v0.10.0/templates/resources/sleep.md.tmpl
@@ -0,0 +1,42 @@
+---
+page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
+subcategory: ""
+description: |-
+{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
+---
+
+# {{.Name}} ({{.Type}})
+
+{{ .Description | trimspace }}
+
+-> In many cases, this resource should be considered a workaround for issues that should be reported and handled in downstream Terraform Provider logic. Downstream resources can usually introduce or adjust retries in their code to handle time delay issues for all Terraform configurations or upstream resources can be improved to better wait for a resource to be fully ready and available.
+
+## Example Usage
+
+### Delay Create Usage
+
+{{ tffile "examples/resources/time_sleep/resource_delay_create.tf" }}
+
+### Delay Destroy Usage
+
+{{ tffile "examples/resources/time_sleep/resource_delay_destroy.tf" }}
+
+### Triggers Usage
+
+{{ tffile "examples/resources/time_sleep/resource_triggers.tf" }}
+
+{{ .SchemaMarkdown | trimspace }}
+
+## Import
+
+This resource can be imported with the `create_duration` and `destroy_duration`, separated by a comma (`,`).
+
+e.g. For 30 seconds create duration with no destroy duration:
+
+{{codefile "shell" "examples/resources/time_sleep/import_create.sh"}}
+
+e.g. For 30 seconds destroy duration with no create duration:
+
+{{codefile "shell" "examples/resources/time_sleep/import_destroy.sh"}}
+
+The `triggers` argument cannot be imported.
\ No newline at end of file
diff --git a/v0.10.0/templates/resources/static.md.tmpl b/v0.10.0/templates/resources/static.md.tmpl
new file mode 100644
index 0000000..fdf8780
--- /dev/null
+++ b/v0.10.0/templates/resources/static.md.tmpl
@@ -0,0 +1,33 @@
+---
+page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
+subcategory: ""
+description: |-
+{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
+---
+
+# {{.Name}} ({{.Type}})
+
+{{ .Description | trimspace }}
+
+-> Further manipulation of incoming or outgoing values can be accomplished with the [`formatdate()` function](https://www.terraform.io/docs/configuration/functions/formatdate.html) and the [`timeadd()` function](https://www.terraform.io/docs/configuration/functions/timeadd.html).
+
+## Example Usage
+
+### Basic Usage
+
+{{ tffile "examples/resources/time_static/resource.tf" }}
+
+### Triggers Usage
+
+{{ tffile "examples/resources/time_static/resource_triggers.tf" }}
+
+{{ .SchemaMarkdown | trimspace }}
+
+
+## Import
+
+This resource can be imported using the UTC RFC3339 value, e.g.
+
+{{codefile "shell" .ImportFile }}
+
+The `triggers` argument cannot be imported.
\ No newline at end of file
diff --git a/v0.10.0/terraform-registry-manifest.json b/v0.10.0/terraform-registry-manifest.json
new file mode 100644
index 0000000..a8286e3
--- /dev/null
+++ b/v0.10.0/terraform-registry-manifest.json
@@ -0,0 +1,6 @@
+{
+ "version": 1,
+ "metadata": {
+ "protocol_versions": ["5.0"]
+ }
+}
\ No newline at end of file
diff --git a/v0.10.0/tools/go.mod b/v0.10.0/tools/go.mod
new file mode 100644
index 0000000..314503b
--- /dev/null
+++ b/v0.10.0/tools/go.mod
@@ -0,0 +1,94 @@
+module tools
+
+go 1.20
+
+require (
+ github.com/hashicorp/copywrite v0.18.0
+ github.com/hashicorp/terraform-plugin-docs v0.16.0
+)
+
+require (
+ github.com/AlecAivazis/survey/v2 v2.3.6 // indirect
+ github.com/Masterminds/goutils v1.1.1 // indirect
+ github.com/Masterminds/semver/v3 v3.1.1 // indirect
+ github.com/Masterminds/sprig/v3 v3.2.2 // indirect
+ github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
+ github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
+ github.com/armon/go-radix v1.0.0 // indirect
+ github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
+ github.com/bgentry/speakeasy v0.1.0 // indirect
+ github.com/bmatcuk/doublestar/v4 v4.6.0 // indirect
+ github.com/bradleyfalzon/ghinstallation/v2 v2.5.0 // indirect
+ github.com/cli/go-gh v1.2.1 // indirect
+ github.com/cli/safeexec v1.0.0 // indirect
+ github.com/cli/shurcooL-graphql v0.0.2 // indirect
+ github.com/cloudflare/circl v1.3.3 // indirect
+ github.com/fatih/color v1.13.0 // indirect
+ github.com/fsnotify/fsnotify v1.5.4 // indirect
+ github.com/go-openapi/errors v0.20.2 // indirect
+ github.com/go-openapi/strfmt v0.21.3 // indirect
+ github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/google/go-github/v45 v45.2.0 // indirect
+ github.com/google/go-github/v53 v53.0.0 // indirect
+ github.com/google/go-querystring v1.1.0 // indirect
+ github.com/google/uuid v1.3.0 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-checkpoint v0.5.0 // indirect
+ github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
+ github.com/hashicorp/go-hclog v1.5.0 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/go-uuid v1.0.3 // indirect
+ github.com/hashicorp/go-version v1.6.0 // indirect
+ github.com/hashicorp/hc-install v0.5.2 // indirect
+ github.com/hashicorp/hcl v1.0.0 // indirect
+ github.com/hashicorp/terraform-exec v0.18.1 // indirect
+ github.com/hashicorp/terraform-json v0.17.1 // indirect
+ github.com/henvic/httpretty v0.0.6 // indirect
+ github.com/huandu/xstrings v1.3.2 // indirect
+ github.com/imdario/mergo v0.3.13 // indirect
+ github.com/inconshreveable/mousetrap v1.0.1 // indirect
+ github.com/jedib0t/go-pretty v4.3.0+incompatible // indirect
+ github.com/jedib0t/go-pretty/v6 v6.4.6 // indirect
+ github.com/joho/godotenv v1.3.0 // indirect
+ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
+ github.com/knadh/koanf v1.5.0 // indirect
+ github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.19 // indirect
+ github.com/mattn/go-runewidth v0.0.13 // indirect
+ github.com/mergestat/timediff v0.0.3 // indirect
+ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
+ github.com/mitchellh/cli v1.1.5 // indirect
+ github.com/mitchellh/copystructure v1.2.0 // indirect
+ github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/mitchellh/reflectwalk v1.0.2 // indirect
+ github.com/muesli/termenv v0.12.0 // indirect
+ github.com/oklog/ulid v1.3.1 // indirect
+ github.com/posener/complete v1.2.3 // indirect
+ github.com/rivo/uniseg v0.2.0 // indirect
+ github.com/rogpeppe/go-internal v1.10.0 // indirect
+ github.com/russross/blackfriday v1.6.0 // indirect
+ github.com/samber/lo v1.37.0 // indirect
+ github.com/shopspring/decimal v1.3.1 // indirect
+ github.com/spf13/cast v1.5.0 // indirect
+ github.com/spf13/cobra v1.6.1 // indirect
+ github.com/spf13/pflag v1.0.5 // indirect
+ github.com/thanhpk/randstr v1.0.4 // indirect
+ github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e // indirect
+ github.com/zclconf/go-cty v1.13.2 // indirect
+ go.mongodb.org/mongo-driver v1.10.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
+ golang.org/x/mod v0.11.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
+ golang.org/x/oauth2 v0.8.0 // indirect
+ golang.org/x/sync v0.1.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
+ golang.org/x/term v0.13.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/protobuf v1.28.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/v0.10.0/tools/go.sum b/v0.10.0/tools/go.sum
new file mode 100644
index 0000000..973e5f7
--- /dev/null
+++ b/v0.10.0/tools/go.sum
@@ -0,0 +1,654 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
+github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw=
+github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
+github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
+github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
+github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
+github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
+github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
+github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
+github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
+github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
+github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
+github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
+github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
+github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
+github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
+github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
+github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
+github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+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/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
+github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg=
+github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
+github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw=
+github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM=
+github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ=
+github.com/aws/aws-sdk-go-v2/service/appconfig v1.4.2/go.mod h1:FZ3HkCe+b10uFZZkFdvf98LHW21k49W8o8J366lqVKY=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8=
+github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk=
+github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g=
+github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc=
+github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
+github.com/bradleyfalzon/ghinstallation/v2 v2.5.0 h1:yaYcGQ7yEIGbsJfW/9z7v1sLiZg/5rSNNXwmMct5XaE=
+github.com/bradleyfalzon/ghinstallation/v2 v2.5.0/go.mod h1:amcvPQMrRkWNdueWOjPytGL25xQGzox7425qMgzo+Vo=
+github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
+github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cli/go-gh v1.2.1 h1:xFrjejSsgPiwXFP6VYynKWwxLQcNJy3Twbu82ZDlR/o=
+github.com/cli/go-gh v1.2.1/go.mod h1:Jxk8X+TCO4Ui/GarwY9tByWm/8zp4jJktzVZNlTW5VM=
+github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI=
+github.com/cli/safeexec v1.0.0/go.mod h1:Z/D4tTN8Vs5gXYHDCbaM1S/anmEDnJb1iW0+EJ5zx3Q=
+github.com/cli/shurcooL-graphql v0.0.2 h1:rwP5/qQQ2fM0TzkUTwtt6E2LbIYf6R+39cUXTa04NYk=
+github.com/cli/shurcooL-graphql v0.0.2/go.mod h1:tlrLmw/n5Q/+4qSvosT+9/W5zc8ZMjnJeYBxSdb4nWA=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
+github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
+github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
+github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
+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/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+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/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
+github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
+github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
+github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
+github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk=
+github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
+github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
+github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
+github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
+github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-openapi/errors v0.20.2 h1:dxy7PGTqEh94zj2E3h1cUmQQWiM1+aeCROfAr02EmK8=
+github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o=
+github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
+github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+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/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.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+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/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.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.4/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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI=
+github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=
+github.com/google/go-github/v53 v53.0.0 h1:T1RyHbSnpHYnoF0ZYKiIPSgPtuJ8G6vgc0MKodXsQDQ=
+github.com/google/go-github/v53 v53.0.0/go.mod h1:XhFRObz+m/l+UCm9b7KSIC3lT3NWSXGt7mOsAWEloao=
+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/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
+github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
+github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
+github.com/hashicorp/copywrite v0.18.0 h1:6f3aBDyQLBXhD6cdGSnsEM37vCDi3JJrkbR9HPBJf5c=
+github.com/hashicorp/copywrite v0.18.0/go.mod h1:6wvQH+ICDoD2bpjO1RJ6fi+h3aY5NeLEM12oTkEtFoc=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.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/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-cleanhttp v0.5.1/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=
+github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
+github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
+github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
+github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
+github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
+github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
+github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
+github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
+github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
+github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hc-install v0.5.2 h1:SfwMFnEXVVirpwkDuSF5kymUOhrUxrTq3udEseZdOD0=
+github.com/hashicorp/hc-install v0.5.2/go.mod h1:9QISwe6newMWIfEiXpzuu1k9HAGtQYgnSH8H9T8wmoI=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
+github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
+github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
+github.com/hashicorp/terraform-exec v0.18.1 h1:LAbfDvNQU1l0NOQlTuudjczVhHj061fNX5H8XZxHlH4=
+github.com/hashicorp/terraform-exec v0.18.1/go.mod h1:58wg4IeuAJ6LVsLUeD2DWZZoc/bYi6dzhLHzxM41980=
+github.com/hashicorp/terraform-json v0.17.1 h1:eMfvh/uWggKmY7Pmb3T85u86E2EQg6EQHgyRwf3RkyA=
+github.com/hashicorp/terraform-json v0.17.1/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o=
+github.com/hashicorp/terraform-plugin-docs v0.16.0 h1:UmxFr3AScl6Wged84jndJIfFccGyBZn52KtMNsS12dI=
+github.com/hashicorp/terraform-plugin-docs v0.16.0/go.mod h1:M3ZrlKBJAbPMtNOPwHicGi1c+hZUh7/g0ifT/z7TVfA=
+github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
+github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
+github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
+github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
+github.com/henvic/httpretty v0.0.6 h1:JdzGzKZBajBfnvlMALXXMVQWxWMF/ofTy8C3/OSUTxs=
+github.com/henvic/httpretty v0.0.6/go.mod h1:X38wLjWXHkXT7r2+uK8LjCMne9rsuNaBLJ+5cU2/Pmo=
+github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec h1:qv2VnGeEQHchGaZ/u7lxST/RaJw+cv273q79D81Xbog=
+github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
+github.com/hjson/hjson-go/v4 v4.0.0 h1:wlm6IYYqHjOdXH1gHev4VoXCaW20HdQAGCxdOEEg2cs=
+github.com/hjson/hjson-go/v4 v4.0.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E=
+github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+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/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
+github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
+github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
+github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
+github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo=
+github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
+github.com/jedib0t/go-pretty/v6 v6.4.6 h1:v6aG9h6Uby3IusSSEjHaZNXpHFhzqMmjXcPq1Rjl9Jw=
+github.com/jedib0t/go-pretty/v6 v6.4.6/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
+github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
+github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
+github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
+github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
+github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
+github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
+github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs=
+github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+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/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
+github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
+github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.3/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/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
+github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
+github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mergestat/timediff v0.0.3 h1:ucCNh4/ZrTPjFZ081PccNbhx9spymCJkFxSzgVuPU+Y=
+github.com/mergestat/timediff v0.0.3/go.mod h1:yvMUaRu2oetc+9IbPLYBJviz6sA7xz8OXMDfhBl7YSI=
+github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
+github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
+github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
+github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
+github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
+github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng=
+github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4=
+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.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/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
+github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc=
+github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A=
+github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk=
+github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
+github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
+github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
+github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
+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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
+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/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
+github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
+github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
+github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
+github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
+github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
+github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
+github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
+github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
+github.com/samber/lo v1.37.0 h1:XjVcB8g6tgUp8rsPsJ2CvhClfImrpL04YpQHXeHPhRw=
+github.com/samber/lo v1.37.0/go.mod h1:9vaz2O4o8oOnK23pd2TrXufcbdbJIa3b6cstBWKpopA=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
+github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
+github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
+github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
+github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
+github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
+github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
+github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
+github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
+github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo=
+github.com/thanhpk/randstr v1.0.4/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
+github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e h1:BuzhfgfWQbX0dWzYzT1zsORLnHRv3bcRcsaUk0VmXA8=
+github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e/go.mod h1:/Tnicc6m/lsJE0irFMA0LfIwTBo4QP7A8IfyIv4zZKI=
+github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
+github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0=
+github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
+go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
+go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
+go.mongodb.org/mongo-driver v1.10.0 h1:UtV6N5k14upNp4LTduX0QCufG124fSu25Wz9tu94GLg=
+go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
+golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME=
+golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
+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=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+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/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
+golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
+golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
+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/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/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-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+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=
+golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+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-20210831042530-f4d43177bf5e/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-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/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=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
+google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+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/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
+gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/v0.10.0/tools/tools.go b/v0.10.0/tools/tools.go
new file mode 100644
index 0000000..b02de1f
--- /dev/null
+++ b/v0.10.0/tools/tools.go
@@ -0,0 +1,22 @@
+// Copyright (c) HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+//go:build generate
+
+package tools
+
+import (
+ // document generation
+ _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs"
+ // copywrite header generation
+ _ "github.com/hashicorp/copywrite"
+)
+
+// Generate copyright headers
+//go:generate go run github.com/hashicorp/copywrite headers -d .. --config ../.copywrite.hcl
+// Format Terraform code for use in documentation.
+// If you do not have Terraform installed, you can remove the formatting command, but it is suggested
+// to ensure the documentation is formatted properly.
+//go:generate terraform fmt -recursive ../examples/
+// Generate documentation.
+//go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate --provider-dir ..