feat: add data sources and organize code (#148)
* feat: add data sources and organize code * fix: ignore unused data source example * fix: add ignore to docs * fix: update CI test to new location * fix: update CI to run acceptance tests * fix: run tests in nix * fix: switch terraform version based on matrix * fix: remove equal sign --------- Signed-off-by: matttrach <matt.trachier@suse.com>
This commit is contained in:
parent
6a43cc60fc
commit
b0b84c1409
|
|
@ -98,12 +98,23 @@ jobs:
|
|||
matrix:
|
||||
# list whatever Terraform versions here you would like to support
|
||||
terraform:
|
||||
- '1.8.*'
|
||||
- '1.9.*'
|
||||
- '1.10.*'
|
||||
- '1.11.*'
|
||||
- '1.12.*'
|
||||
# the latest patch of each version will be used
|
||||
- '1.5.0'
|
||||
- '1.6.0'
|
||||
- '1.7.0'
|
||||
- '1.8.0'
|
||||
- '1.9.0'
|
||||
- '1.10.0'
|
||||
- '1.11.0'
|
||||
- '1.12.0'
|
||||
- '1.13.0'
|
||||
steps:
|
||||
- name: install-nix
|
||||
run: |
|
||||
curl -L https://nixos.org/nix/install | sh
|
||||
source /home/runner/.nix-profile/etc/profile.d/nix.sh
|
||||
nix --version
|
||||
which nix
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 https://github.com/actions/checkout
|
||||
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 https://github.com/actions/setup-go
|
||||
with:
|
||||
|
|
@ -113,9 +124,12 @@ jobs:
|
|||
with:
|
||||
terraform_version: ${{ matrix.terraform }}
|
||||
terraform_wrapper: false
|
||||
- run: go mod download
|
||||
- run: go install gotest.tools/gotestsum@ddd0b05a6878e2e8257a2abe6e7df66cebc53d0e # v1.12.3
|
||||
- run: make test
|
||||
- run: terraform fmt -check -recursive
|
||||
- run: pushd ./examples/use-cases/basic; terraform init -input=false; popd
|
||||
- run: pushd ./examples/use-cases/basic; terraform validate -no-color; popd
|
||||
- name: run tests
|
||||
shell: /home/runner/.nix-profile/bin/nix develop --ignore-environment --extra-experimental-features nix-command --extra-experimental-features flakes --keep HOME --keep NIX_SSL_CERT_FILE --keep NIX_ENV_LOADED --keep TERM --command bash -e {0}
|
||||
run: |
|
||||
go mod download
|
||||
go install gotest.tools/gotestsum@ddd0b05a6878e2e8257a2abe6e7df66cebc53d0e # v1.12.3
|
||||
terraform fmt -check -recursive
|
||||
tfswitch -s ${{ matrix.terraform }}
|
||||
make test
|
||||
make testacc
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
version: "2"
|
||||
linters:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
# https://goreleaser.com for documentation
|
||||
|
||||
|
|
|
|||
|
|
@ -20,14 +20,12 @@ test:
|
|||
|
||||
testacc: build
|
||||
export REPO_ROOT="../../../."; \
|
||||
export TF_CLI_CONFIG_FILE="../../../test/.terraformrc"; \
|
||||
pushd ./test; \
|
||||
gotestsum --format standard-verbose --jsonfile report.json --post-run-command "./summarize.sh" -- ./... -v -p=1 -timeout=300s; \
|
||||
popd;
|
||||
|
||||
debug: build
|
||||
export REPO_ROOT="../../../."; \
|
||||
export TF_CLI_CONFIG_FILE="../../../test/.terraformrc"; \
|
||||
export TF_LOG=DEBUG; \
|
||||
pushd ./test; \
|
||||
gotestsum --format standard-verbose --jsonfile report.json --post-run-command "./summarize.sh" -- ./... -v -p=1 -timeout=300s; \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "file_local Data Source - file"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
Local File DataSource
|
||||
---
|
||||
|
||||
# file_local (Data Source)
|
||||
|
||||
Local File DataSource
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
# tflint-ignore: terraform_unused_declarations
|
||||
data "file_local" "basic_example" {
|
||||
name = "example.txt"
|
||||
directory = "."
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `directory` (String) The directory where the file exists.
|
||||
- `name` (String) File name, required.
|
||||
|
||||
### Optional
|
||||
|
||||
- `hmac_secret_key` (String, Sensitive) A string used to generate the file identifier, you can pass this value in the environment variable `TF_FILE_HMAC_SECRET_KEY`.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `contents` (String) The file contents.
|
||||
- `id` (String) Identifier derived from sha256+HMAC hash of file contents.
|
||||
- `permissions` (String) The file permissions.
|
||||
|
|
@ -12,8 +12,6 @@ description: |-
|
|||
## Example Usage
|
||||
|
||||
```terraform
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
# this provider has no configuration currently
|
||||
provider "file" {}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ Local File resource
|
|||
## Example Usage
|
||||
|
||||
```terraform
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
resource "file_local" "basic_example" {
|
||||
name = "example.txt"
|
||||
contents = "An example implementation writing a local file."
|
||||
|
|
@ -59,8 +57,6 @@ Import is supported using the following syntax:
|
|||
The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:
|
||||
|
||||
```shell
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
# echo "Test data" > data.txt
|
||||
# FILEPATH="./data.txt"
|
||||
# TF_FILE_HMAC_SECRET_KEY="super-secret-key"
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
data "file_local" "example" {
|
||||
configurable_attribute = "some-value"
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
# tflint-ignore: terraform_unused_declarations
|
||||
data "file_local" "basic_example" {
|
||||
name = "example.txt"
|
||||
directory = "."
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
# this provider has no configuration currently
|
||||
provider "file" {}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
# echo "Test data" > data.txt
|
||||
# FILEPATH="./data.txt"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
resource "file_local" "basic_example" {
|
||||
name = "example.txt"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
provider_installation {
|
||||
dev_overrides {
|
||||
"rancher/file" = "../../../bin"
|
||||
"rancher/file" = "../../../../bin"
|
||||
}
|
||||
direct {
|
||||
exclude = []
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
|
||||
terraform {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
provider "file" {}
|
||||
|
||||
|
|
@ -12,3 +12,8 @@ resource "file_local" "basic" {
|
|||
directory = local.directory
|
||||
contents = "An example of the \"most basic\" implementation writing a local file."
|
||||
}
|
||||
|
||||
data "file_local" "basic" {
|
||||
name = file_local.basic.name
|
||||
directory = file_local.basic.directory
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
|
||||
output "file_resource" {
|
||||
value = jsonencode(file_local.basic)
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "file_data_source" {
|
||||
value = jsonencode(data.file_local.basic)
|
||||
sensitive = true
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
variable "directory" {
|
||||
type = string
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
provider_installation {
|
||||
dev_overrides {
|
||||
"rancher/file" = "../../../bin"
|
||||
"rancher/file" = "../../../../bin"
|
||||
}
|
||||
direct {
|
||||
exclude = []
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
|
||||
terraform {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
provider "file" {}
|
||||
|
||||
|
|
@ -26,3 +26,8 @@ resource "file_local" "protected_env" {
|
|||
directory = local.directory
|
||||
contents = "An example implementation of a protected file."
|
||||
}
|
||||
|
||||
data "file_local" "protected" {
|
||||
name = file_local.protected.name
|
||||
directory = file_local.protected.directory
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
|
||||
output "file_resource" {
|
||||
value = jsonencode(file_local.protected)
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "file_resource_env" {
|
||||
value = jsonencode(file_local.protected_env)
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "file_data_source" {
|
||||
value = jsonencode(data.file_local.protected)
|
||||
sensitive = true
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
variable "directory" {
|
||||
type = string
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.5.0"
|
||||
required_providers {
|
||||
file = {
|
||||
source = "rancher/file"
|
||||
version = ">= 0.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,11 +20,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1756128520,
|
||||
"narHash": "sha256-R94HxJBi+RK1iCm8Y4Q9pdrHZl0GZoDPIaYwjxRNPh4=",
|
||||
"lastModified": 1756819007,
|
||||
"narHash": "sha256-12V64nKG/O/guxSYnr5/nq1EfqwJCdD2+cIGmhz3nrE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c53baa6685261e5253a1c355a1b322f82674a824",
|
||||
"rev": "aaff8c16d7fc04991cac6245bee1baa31f72b1e1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
)
|
||||
|
||||
// Ensure provider defined types fully satisfy framework interfaces.
|
||||
var _ datasource.DataSource = &ExampleDataSource{}
|
||||
|
||||
func NewExampleDataSource() datasource.DataSource {
|
||||
return &ExampleDataSource{}
|
||||
}
|
||||
|
||||
// ExampleDataSource defines the data source implementation.
|
||||
type ExampleDataSource struct {
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// ExampleDataSourceModel describes the data source data model.
|
||||
type ExampleDataSourceModel struct {
|
||||
ConfigurableAttribute types.String `tfsdk:"configurable_attribute"`
|
||||
Id types.String `tfsdk:"id"`
|
||||
}
|
||||
|
||||
func (d *ExampleDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_example"
|
||||
}
|
||||
|
||||
func (d *ExampleDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
// This description is used by the documentation generator and the language server.
|
||||
MarkdownDescription: "Example data source",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"configurable_attribute": schema.StringAttribute{
|
||||
MarkdownDescription: "Example configurable attribute",
|
||||
Optional: true,
|
||||
},
|
||||
"id": schema.StringAttribute{
|
||||
MarkdownDescription: "Example identifier",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *ExampleDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
// Prevent panic if the provider has not been configured.
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
|
||||
client, ok := req.ProviderData.(*http.Client)
|
||||
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Data Source Configure Type",
|
||||
fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.client = client
|
||||
}
|
||||
|
||||
func (d *ExampleDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
var data ExampleDataSourceModel
|
||||
|
||||
// Read Terraform configuration data into the model
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
// If applicable, this is a great opportunity to initialize any necessary
|
||||
// provider client data and make a call using it.
|
||||
// httpResp, err := d.client.Do(httpReq)
|
||||
// if err != nil {
|
||||
// resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read example, got error: %s", err))
|
||||
// return
|
||||
// }
|
||||
|
||||
// For the purposes of this example code, hardcoding a response value to
|
||||
// save into the Terraform state.
|
||||
data.Id = types.StringValue("example-id")
|
||||
|
||||
// Write logs using the tflog package
|
||||
// Documentation: https://terraform.io/plugin/log
|
||||
tflog.Trace(ctx, "read a data source")
|
||||
|
||||
// Save data into Terraform state
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
|
||||
"github.com/hashicorp/terraform-plugin-testing/statecheck"
|
||||
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
|
||||
)
|
||||
|
||||
func TestAccExampleDataSource(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
Steps: []resource.TestStep{
|
||||
// Read testing
|
||||
{
|
||||
Config: testAccExampleDataSourceConfig,
|
||||
ConfigStateChecks: []statecheck.StateCheck{
|
||||
statecheck.ExpectKnownValue(
|
||||
"data.file_example.test",
|
||||
tfjsonpath.New("id"),
|
||||
knownvalue.StringExact("example-id"),
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const testAccExampleDataSourceConfig = `
|
||||
data "file_example" "test" {
|
||||
configurable_attribute = "example"
|
||||
}
|
||||
`
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
)
|
||||
|
||||
// The `var _` is a special Go construct that results in an unusable variable.
|
||||
// The purpose of these lines is to make sure our LocalFileResource correctly implements the `resource.Resource“ interface.
|
||||
// These will fail at compilation time if the implementation is not satisfied.
|
||||
var _ datasource.DataSource = &LocalDataSource{}
|
||||
|
||||
func NewLocalDataSource() datasource.DataSource {
|
||||
return &LocalDataSource{}
|
||||
}
|
||||
|
||||
type LocalDataSource struct {
|
||||
client fileClient
|
||||
}
|
||||
|
||||
type LocalDataSourceModel struct {
|
||||
Id types.String `tfsdk:"id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Directory types.String `tfsdk:"directory"`
|
||||
Contents types.String `tfsdk:"contents"`
|
||||
Permissions types.String `tfsdk:"permissions"`
|
||||
HmacSecretKey types.String `tfsdk:"hmac_secret_key"`
|
||||
}
|
||||
|
||||
func (r *LocalDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_local" // file_local datasource
|
||||
}
|
||||
|
||||
func (r *LocalDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
MarkdownDescription: "Local File DataSource",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"name": schema.StringAttribute{
|
||||
MarkdownDescription: "File name, required.",
|
||||
Required: true,
|
||||
},
|
||||
"directory": schema.StringAttribute{
|
||||
MarkdownDescription: "The directory where the file exists.",
|
||||
Required: true,
|
||||
},
|
||||
"hmac_secret_key": schema.StringAttribute{
|
||||
MarkdownDescription: "A string used to generate the file identifier, " +
|
||||
"you can pass this value in the environment variable `TF_FILE_HMAC_SECRET_KEY`. ",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
"contents": schema.StringAttribute{
|
||||
MarkdownDescription: "The file contents.",
|
||||
Computed: true,
|
||||
},
|
||||
"permissions": schema.StringAttribute{
|
||||
MarkdownDescription: "The file permissions.",
|
||||
Computed: true,
|
||||
},
|
||||
"id": schema.StringAttribute{
|
||||
MarkdownDescription: "Identifier derived from sha256+HMAC hash of file contents. ",
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LocalDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
||||
// Prevent panic if the provider has not been configured.
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Read runs before all other resources are run, datasources only get the Read function.
|
||||
func (r *LocalDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||
tflog.Debug(ctx, fmt.Sprintf("Request Object: %#v", req))
|
||||
|
||||
// Allow the ability to inject a file client, but use the osFileClient by default.
|
||||
if r.client == nil {
|
||||
tflog.Debug(ctx, "Configuring client with default osFileClient.")
|
||||
r.client = &osFileClient{}
|
||||
}
|
||||
|
||||
var config LocalDataSourceModel
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
cName := config.Name.ValueString()
|
||||
cDirectory := config.Directory.ValueString()
|
||||
cPerm := config.Permissions.ValueString()
|
||||
cHmacSecretKey := config.HmacSecretKey.ValueString()
|
||||
|
||||
cKey := cHmacSecretKey
|
||||
if cKey == "" {
|
||||
tflog.Debug(ctx, "Checking for secret key in environment variable TF_FILE_HMAC_SECRET_KEY.")
|
||||
cKey = os.Getenv("TF_FILE_HMAC_SECRET_KEY")
|
||||
}
|
||||
|
||||
if cKey == "" {
|
||||
tflog.Debug(ctx, "Key not found, attempting to use constant.")
|
||||
cKey = unprotectedHmacSecret // this is a constant defined in file_local_resource.go
|
||||
}
|
||||
|
||||
perm, contents, err := r.client.Read(cDirectory, cName)
|
||||
if err != nil && err.Error() == "File not found." {
|
||||
resp.State.RemoveResource(ctx)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error reading file: ", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// update state with actual contents
|
||||
config.Contents = types.StringValue(contents)
|
||||
id, err := calculateId(contents, cKey)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error reading file: ", "Problem calculating id from key: "+err.Error())
|
||||
return
|
||||
}
|
||||
config.Id = types.StringValue(id)
|
||||
|
||||
if perm != cPerm {
|
||||
// update the state with the actual mode
|
||||
config.Permissions = types.StringValue(perm)
|
||||
}
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &config)...)
|
||||
tflog.Debug(ctx, fmt.Sprintf("Response Object: %#v", *resp))
|
||||
}
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
|
||||
"github.com/hashicorp/terraform-plugin-go/tftypes"
|
||||
)
|
||||
|
||||
func TestLocalDataSourceMetadata(t *testing.T) {
|
||||
t.Run("Metadata function", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
fit LocalDataSource
|
||||
want datasource.MetadataResponse
|
||||
}{
|
||||
{"Basic test", LocalDataSource{}, datasource.MetadataResponse{TypeName: "file_local"}},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
res := datasource.MetadataResponse{}
|
||||
tc.fit.Metadata(context.Background(), datasource.MetadataRequest{ProviderTypeName: "file"}, &res)
|
||||
got := res
|
||||
if got != tc.want {
|
||||
t.Errorf("%#v.Metadata() is %v; want %v", tc.fit, got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestLocalDataSourceRead(t *testing.T) {
|
||||
t.Run("Read function", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
fit LocalDataSource
|
||||
have datasource.ReadRequest
|
||||
want datasource.ReadResponse
|
||||
setup map[string]string
|
||||
}{
|
||||
{
|
||||
"Unprotected",
|
||||
LocalDataSource{client: &memoryFileClient{}},
|
||||
// have
|
||||
getDataSourceReadRequest(t, map[string]string{
|
||||
"id": "60cef95046105ff4522c0c1f1aeeeba43d0d729dbcabdd8846c317c98cac60a2",
|
||||
"name": "read.tmp",
|
||||
"directory": defaultDirectory,
|
||||
"permissions": defaultPerm,
|
||||
"contents": "this is an unprotected read test",
|
||||
"hmac_secret_key": defaultHmacSecretKey,
|
||||
}),
|
||||
// want
|
||||
getDataSourceReadResponse(t, map[string]string{
|
||||
"id": "60cef95046105ff4522c0c1f1aeeeba43d0d729dbcabdd8846c317c98cac60a2",
|
||||
"name": "read.tmp",
|
||||
"directory": defaultDirectory,
|
||||
"permissions": defaultPerm,
|
||||
"contents": "this is an unprotected read test",
|
||||
"hmac_secret_key": defaultHmacSecretKey,
|
||||
}),
|
||||
map[string]string{
|
||||
"mode": defaultPerm,
|
||||
"directory": defaultDirectory,
|
||||
"name": "read.tmp",
|
||||
"contents": "this is an unprotected read test",
|
||||
},
|
||||
},
|
||||
{
|
||||
"Protected",
|
||||
LocalDataSource{client: &memoryFileClient{}},
|
||||
// have
|
||||
getDataSourceReadRequest(t, map[string]string{
|
||||
"id": "ec4407ba53b2c40ac2ac18ff7372a6fe6e4f7f8aa04f340503aefc7d9a5fa4e1",
|
||||
"name": "read_protected.tmp",
|
||||
"directory": defaultDirectory,
|
||||
"permissions": defaultPerm,
|
||||
"contents": "this is a protected read test",
|
||||
"hmac_secret_key": "this-is-a-test-key",
|
||||
}),
|
||||
// want
|
||||
getDataSourceReadResponse(t, map[string]string{
|
||||
"id": "ec4407ba53b2c40ac2ac18ff7372a6fe6e4f7f8aa04f340503aefc7d9a5fa4e1",
|
||||
"name": "read_protected.tmp",
|
||||
"directory": defaultDirectory,
|
||||
"permissions": defaultPerm,
|
||||
"contents": "this is a protected read test",
|
||||
"hmac_secret_key": "this-is-a-test-key",
|
||||
}),
|
||||
// reality
|
||||
map[string]string{
|
||||
"mode": defaultPerm,
|
||||
"directory": defaultDirectory,
|
||||
"name": "read_protected.tmp",
|
||||
"contents": "this is a protected read test",
|
||||
},
|
||||
},
|
||||
{
|
||||
"Protected with content update",
|
||||
LocalDataSource{client: &memoryFileClient{}},
|
||||
// have
|
||||
getDataSourceReadRequest(t, map[string]string{
|
||||
"id": "ec4407ba53b2c40ac2ac18ff7372a6fe6e4f7f8aa04f340503aefc7d9a5fa4e1",
|
||||
"name": "read_protected_content.tmp",
|
||||
"directory": defaultDirectory,
|
||||
"permissions": defaultPerm,
|
||||
"contents": "this is a protected read test",
|
||||
"hmac_secret_key": "this-is-a-test-key",
|
||||
}),
|
||||
// want
|
||||
getDataSourceReadResponse(t, map[string]string{
|
||||
"id": "84326116e261654e44ca3cb73fa026580853794062d472bc817b7ec2c82ff648",
|
||||
"name": "read_protected_content.tmp",
|
||||
"directory": defaultDirectory,
|
||||
"permissions": defaultPerm,
|
||||
"contents": "this is a change in contents in the real file",
|
||||
"hmac_secret_key": "this-is-a-test-key",
|
||||
}),
|
||||
// reality
|
||||
map[string]string{
|
||||
"mode": defaultPerm,
|
||||
"directory": defaultDirectory,
|
||||
"name": "read_protected_content.tmp",
|
||||
"contents": "this is a change in contents in the real file",
|
||||
},
|
||||
},
|
||||
{
|
||||
"Protected with mode update",
|
||||
LocalDataSource{client: &memoryFileClient{}},
|
||||
// have
|
||||
getDataSourceReadRequest(t, map[string]string{
|
||||
"id": "ec4407ba53b2c40ac2ac18ff7372a6fe6e4f7f8aa04f340503aefc7d9a5fa4e1",
|
||||
"name": "read_protected_mode.tmp",
|
||||
"directory": defaultDirectory,
|
||||
"permissions": defaultPerm,
|
||||
"contents": "this is a protected read test",
|
||||
"hmac_secret_key": "this-is-a-test-key",
|
||||
}),
|
||||
// want
|
||||
getDataSourceReadResponse(t, map[string]string{
|
||||
"id": "ec4407ba53b2c40ac2ac18ff7372a6fe6e4f7f8aa04f340503aefc7d9a5fa4e1",
|
||||
"name": "read_protected_mode.tmp",
|
||||
"directory": defaultDirectory,
|
||||
"permissions": "0755",
|
||||
"contents": "this is a protected read test",
|
||||
"hmac_secret_key": "this-is-a-test-key",
|
||||
}),
|
||||
// reality
|
||||
map[string]string{
|
||||
"mode": "0755",
|
||||
"directory": defaultDirectory,
|
||||
"name": "read_protected_mode.tmp",
|
||||
"contents": "this is a protected read test",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := tc.fit.client.Create(tc.setup["directory"], tc.setup["name"], tc.setup["contents"], tc.setup["mode"]); err != nil {
|
||||
t.Errorf("Error setting up: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := tc.fit.client.Delete(tc.setup["directory"], tc.setup["name"]); err != nil {
|
||||
t.Errorf("Error tearing down: %v", err)
|
||||
}
|
||||
}()
|
||||
r := getDataSourceReadResponseContainer()
|
||||
tc.fit.Read(context.Background(), tc.have, &r)
|
||||
got := r
|
||||
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||
t.Errorf("Read() mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// *** Test Helper Functions *** //
|
||||
|
||||
func getDataSourceReadRequest(t *testing.T, data map[string]string) datasource.ReadRequest {
|
||||
stateMap := make(map[string]tftypes.Value)
|
||||
for key, value := range data {
|
||||
if slices.Contains(booleanFields, key) { // booleanFields is a constant
|
||||
v, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
t.Errorf("Error converting %s to bool %s: ", value, err.Error())
|
||||
}
|
||||
stateMap[key] = tftypes.NewValue(tftypes.Bool, v)
|
||||
} else {
|
||||
stateMap[key] = tftypes.NewValue(tftypes.String, value)
|
||||
}
|
||||
}
|
||||
stateValue := tftypes.NewValue(getDataSourceObjectAttributeTypes(), stateMap)
|
||||
return datasource.ReadRequest{
|
||||
Config: tfsdk.Config{
|
||||
Raw: stateValue,
|
||||
Schema: getLocalDataSourceSchema().Schema,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getDataSourceReadResponseContainer() datasource.ReadResponse {
|
||||
return datasource.ReadResponse{
|
||||
State: tfsdk.State{Schema: getLocalDataSourceSchema().Schema},
|
||||
}
|
||||
}
|
||||
|
||||
func getDataSourceReadResponse(t *testing.T, data map[string]string) datasource.ReadResponse {
|
||||
stateMap := make(map[string]tftypes.Value)
|
||||
for key, value := range data {
|
||||
if slices.Contains(booleanFields, key) { // booleanFields is a constant
|
||||
v, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
t.Errorf("Error converting %s to bool %s: ", value, err.Error())
|
||||
}
|
||||
stateMap[key] = tftypes.NewValue(tftypes.Bool, v)
|
||||
} else {
|
||||
stateMap[key] = tftypes.NewValue(tftypes.String, value)
|
||||
}
|
||||
}
|
||||
stateValue := tftypes.NewValue(getDataSourceObjectAttributeTypes(), stateMap)
|
||||
return datasource.ReadResponse{
|
||||
State: tfsdk.State{
|
||||
Raw: stateValue,
|
||||
Schema: getLocalDataSourceSchema().Schema,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getDataSourceObjectAttributeTypes() tftypes.Object {
|
||||
return tftypes.Object{
|
||||
AttributeTypes: map[string]tftypes.Type{
|
||||
"id": tftypes.String,
|
||||
"name": tftypes.String,
|
||||
"directory": tftypes.String,
|
||||
"permissions": tftypes.String,
|
||||
"contents": tftypes.String,
|
||||
"hmac_secret_key": tftypes.String,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getLocalDataSourceSchema() *datasource.SchemaResponse {
|
||||
var testResource LocalDataSource
|
||||
r := &datasource.SchemaResponse{}
|
||||
testResource.Schema(context.Background(), datasource.SchemaRequest{}, r)
|
||||
return r
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -10,8 +10,6 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework-validators/boolvalidator"
|
||||
|
|
@ -34,6 +32,8 @@ import (
|
|||
var _ resource.Resource = &LocalResource{}
|
||||
var _ resource.ResourceWithImportState = &LocalResource{}
|
||||
|
||||
const unprotectedHmacSecret = "this-is-the-hmac-secret-key-that-will-be-used-to-calculate-the-hash-of-unprotected-files"
|
||||
|
||||
// An interface for defining custom file managers.
|
||||
type fileClient interface {
|
||||
Create(directory string, name string, data string, permissions string) error
|
||||
|
|
@ -43,58 +43,6 @@ type fileClient interface {
|
|||
Delete(directory string, name string) error
|
||||
}
|
||||
|
||||
// The default fileClient, using the os package.
|
||||
type osFileClient struct{}
|
||||
|
||||
var _ fileClient = &osFileClient{} // make sure the osFileClient implements the fileClient
|
||||
|
||||
func (c *osFileClient) Create(directory string, name string, data string, permissions string) error {
|
||||
path := filepath.Join(directory, name)
|
||||
modeInt, err := strconv.ParseUint(permissions, 8, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(path, []byte(data), os.FileMode(modeInt))
|
||||
}
|
||||
func (c *osFileClient) Read(directory string, name string) (string, string, error) {
|
||||
path := filepath.Join(directory, name)
|
||||
info, err := os.Stat(path)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
return "", "", fmt.Errorf("file not found")
|
||||
}
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
mode := fmt.Sprintf("%#o", info.Mode().Perm())
|
||||
contents, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return mode, string(contents), nil
|
||||
}
|
||||
func (c *osFileClient) Update(currentDirectory string, currentName string, newDirectory string, newName string, data string, permissions string) error {
|
||||
currentPath := filepath.Join(currentDirectory, currentName)
|
||||
newPath := filepath.Join(newDirectory, newName)
|
||||
if currentPath != newPath {
|
||||
err := os.Rename(currentPath, newPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
modeInt, err := strconv.ParseUint(permissions, 8, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.WriteFile(newPath, []byte(data), os.FileMode(modeInt)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (c *osFileClient) Delete(directory string, name string) error {
|
||||
path := filepath.Join(directory, name)
|
||||
return os.Remove(path)
|
||||
}
|
||||
|
||||
func NewLocalResource() resource.Resource {
|
||||
return &LocalResource{}
|
||||
}
|
||||
|
|
@ -212,6 +160,7 @@ func (r *LocalResource) Create(ctx context.Context, req resource.CreateRequest,
|
|||
var err error
|
||||
|
||||
// Allow the ability to inject a file client, but use the osFileClient by default.
|
||||
// see file_os_client.go
|
||||
if r.client == nil {
|
||||
tflog.Debug(ctx, "Configuring client with default osFileClient.")
|
||||
r.client = &osFileClient{}
|
||||
|
|
@ -245,7 +194,7 @@ func (r *LocalResource) Create(ctx context.Context, req resource.CreateRequest,
|
|||
return
|
||||
} // at this point we have an id, key, contents, protected is true, and our calculated id matches what was provided
|
||||
} else {
|
||||
id, err = calculateId(contents, "this-is-the-hmac-secret-key-that-will-be-used-to-calculate-the-hash-of-unprotected-files")
|
||||
id, err = calculateId(contents, unprotectedHmacSecret)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error creating file: ", "Problem calculating id from hard coded key: "+err.Error())
|
||||
return
|
||||
|
|
@ -369,7 +318,7 @@ func (r *LocalResource) Update(ctx context.Context, req resource.UpdateRequest,
|
|||
return
|
||||
}
|
||||
} else {
|
||||
id, err := calculateId(cContents, "this-is-the-hmac-secret-key-that-will-be-used-to-calculate-the-hash-of-unprotected-files")
|
||||
id, err := calculateId(cContents, unprotectedHmacSecret)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error updating file: ", "Problem calculating id from hard coded key: "+err.Error())
|
||||
return
|
||||
|
|
@ -405,7 +354,7 @@ func (r *LocalResource) Update(ctx context.Context, req resource.UpdateRequest,
|
|||
return
|
||||
}
|
||||
} else {
|
||||
_, err := calculateId(rContents, "this-is-the-hmac-secret-key-that-will-be-used-to-calculate-the-hash-of-unprotected-files")
|
||||
_, err := calculateId(rContents, unprotectedHmacSecret)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Error updating file: ", "Problem calculating id from hard coded key: "+err.Error())
|
||||
return
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package provider
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
|
@ -709,43 +708,3 @@ func getLocalResourceSchema() *resource.SchemaResponse {
|
|||
testResource.Schema(context.Background(), resource.SchemaRequest{}, r)
|
||||
return r
|
||||
}
|
||||
|
||||
// type fileClient interface {
|
||||
// Create(directory string, name string, data string, permissions string) error
|
||||
// // If file isn't found the error message must have err.Error() == "File not found."
|
||||
// Read(directory string, name string) (string, string, error)// permissions, contents, error
|
||||
// Update(currentDirectory string, currentName string, newDirectory string, newName string, data string, permissions string) error
|
||||
// Delete(directory string, name string) error
|
||||
// }
|
||||
|
||||
type memoryFileClient struct {
|
||||
file map[string]string
|
||||
}
|
||||
|
||||
var _ fileClient = &memoryFileClient{} // make sure the memoryFileClient implements the fileClient
|
||||
func (c *memoryFileClient) Create(directory string, name string, data string, permissions string) error {
|
||||
|
||||
c.file = make(map[string]string)
|
||||
c.file["directory"] = directory
|
||||
c.file["name"] = name
|
||||
c.file["contents"] = data
|
||||
c.file["permissions"] = permissions
|
||||
return nil
|
||||
}
|
||||
func (c *memoryFileClient) Read(directory string, name string) (string, string, error) {
|
||||
if c.file["directory"] == "" || c.file["name"] == "" {
|
||||
return "", "", fmt.Errorf("file not found")
|
||||
}
|
||||
return c.file["permissions"], c.file["contents"], nil
|
||||
}
|
||||
func (c *memoryFileClient) Update(currentDirectory string, currentName string, newDirectory string, newName string, data string, permissions string) error {
|
||||
c.file["directory"] = newDirectory
|
||||
c.file["name"] = newName
|
||||
c.file["contents"] = data
|
||||
c.file["permissions"] = permissions
|
||||
return nil
|
||||
}
|
||||
func (c *memoryFileClient) Delete(directory string, name string) error {
|
||||
c.file = nil
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package local
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type memoryFileClient struct {
|
||||
file map[string]string
|
||||
}
|
||||
|
||||
var _ fileClient = &memoryFileClient{} // make sure the memoryFileClient implements the fileClient
|
||||
|
||||
func (c *memoryFileClient) Create(directory string, name string, data string, permissions string) error {
|
||||
|
||||
c.file = make(map[string]string)
|
||||
c.file["directory"] = directory
|
||||
c.file["name"] = name
|
||||
c.file["contents"] = data
|
||||
c.file["permissions"] = permissions
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *memoryFileClient) Read(directory string, name string) (string, string, error) {
|
||||
if c.file["directory"] == "" || c.file["name"] == "" {
|
||||
return "", "", fmt.Errorf("file not found")
|
||||
}
|
||||
return c.file["permissions"], c.file["contents"], nil
|
||||
}
|
||||
|
||||
func (c *memoryFileClient) Update(currentDirectory string, currentName string, newDirectory string, newName string, data string, permissions string) error {
|
||||
c.file["directory"] = newDirectory
|
||||
c.file["name"] = newName
|
||||
c.file["contents"] = data
|
||||
c.file["permissions"] = permissions
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *memoryFileClient) Delete(directory string, name string) error {
|
||||
c.file = nil
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package local
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// The default fileClient, using the os package.
|
||||
type osFileClient struct{}
|
||||
|
||||
var _ fileClient = &osFileClient{} // make sure the osFileClient implements the fileClient
|
||||
|
||||
func (c *osFileClient) Create(directory string, name string, data string, permissions string) error {
|
||||
path := filepath.Join(directory, name)
|
||||
modeInt, err := strconv.ParseUint(permissions, 8, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(path, []byte(data), os.FileMode(modeInt))
|
||||
}
|
||||
|
||||
func (c *osFileClient) Read(directory string, name string) (string, string, error) {
|
||||
path := filepath.Join(directory, name)
|
||||
info, err := os.Stat(path)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
return "", "", fmt.Errorf("file not found")
|
||||
}
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
mode := fmt.Sprintf("%#o", info.Mode().Perm())
|
||||
contents, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return mode, string(contents), nil
|
||||
}
|
||||
|
||||
func (c *osFileClient) Update(currentDirectory string, currentName string, newDirectory string, newName string, data string, permissions string) error {
|
||||
currentPath := filepath.Join(currentDirectory, currentName)
|
||||
newPath := filepath.Join(newDirectory, newName)
|
||||
if currentPath != newPath {
|
||||
err := os.Rename(currentPath, newPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
modeInt, err := strconv.ParseUint(permissions, 8, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.WriteFile(newPath, []byte(data), os.FileMode(modeInt)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *osFileClient) Delete(directory string, name string) error {
|
||||
path := filepath.Join(directory, name)
|
||||
return os.Remove(path)
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/hashicorp/terraform-plugin-framework/provider"
|
||||
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/rancher/terraform-provider-file/internal/provider/local"
|
||||
)
|
||||
|
||||
// The `var _` is a special Go construct that results in an unusable variable.
|
||||
|
|
@ -48,13 +49,13 @@ func (p *FileProvider) Configure(ctx context.Context, req provider.ConfigureRequ
|
|||
|
||||
func (p *FileProvider) Resources(ctx context.Context) []func() resource.Resource {
|
||||
return []func() resource.Resource{
|
||||
NewLocalResource,
|
||||
local.NewLocalResource,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *FileProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
|
||||
return []func() datasource.DataSource{
|
||||
// NewExampleDataSource,
|
||||
local.NewLocalDataSource,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
provider_installation {
|
||||
dev_overrides {
|
||||
"rancher/file" = "../../../bin"
|
||||
"rancher/file" = "../../../../bin"
|
||||
}
|
||||
direct {
|
||||
exclude = []
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
|
||||
package basic
|
||||
|
||||
import (
|
||||
|
|
@ -14,7 +12,7 @@ func TestBasic(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
id := util.GetId()
|
||||
directory := "basic"
|
||||
directory := "local/basic"
|
||||
repoRoot, err := util.GetRepoRoot(t)
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting git root directory: %v", err)
|
||||
|
|
@ -40,6 +38,7 @@ func TestBasic(t *testing.T) {
|
|||
},
|
||||
EnvVars: map[string]string{
|
||||
"TF_DATA_DIR": testDir,
|
||||
"TF_CLI_CONFIG_FILE": filepath.Join(repoRoot, "test", ".terraformrc"),
|
||||
"TF_IN_AUTOMATION": "1",
|
||||
"TF_CLI_ARGS_init": "-no-color",
|
||||
"TF_CLI_ARGS_plan": "-no-color",
|
||||
|
|
@ -50,6 +49,7 @@ func TestBasic(t *testing.T) {
|
|||
RetryableTerraformErrors: util.GetRetryableTerraformErrors(),
|
||||
NoColor: true,
|
||||
Upgrade: true,
|
||||
// ExtraArgs: terraform.ExtraArgs{ Output: []string{"-json"} },
|
||||
})
|
||||
|
||||
_, err = terraform.InitAndApplyE(t, terraformOptions)
|
||||
|
|
@ -58,6 +58,10 @@ func TestBasic(t *testing.T) {
|
|||
util.TearDown(t, testDir, terraformOptions)
|
||||
t.Fatalf("Error creating file: %s", err)
|
||||
}
|
||||
_, err = terraform.OutputAllE(t, terraformOptions)
|
||||
if err != nil {
|
||||
t.Log("Output failed, moving along...")
|
||||
}
|
||||
|
||||
fileExists, err := util.CheckFileExists(filepath.Join(testDir, "basic_test.txt"))
|
||||
if err != nil {
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
|
||||
package protected
|
||||
|
||||
import (
|
||||
|
|
@ -13,7 +11,7 @@ import (
|
|||
func TestProtectedBasic(t *testing.T) {
|
||||
t.Parallel()
|
||||
id := util.GetId()
|
||||
directory := "protected"
|
||||
directory := "local/protected"
|
||||
repoRoot, err := util.GetRepoRoot(t)
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting git root directory: %v", err)
|
||||
|
|
@ -41,6 +39,7 @@ func TestProtectedBasic(t *testing.T) {
|
|||
EnvVars: map[string]string{
|
||||
"TF_DATA_DIR": testDir,
|
||||
"TF_FILE_HMAC_SECRET_KEY": "thisisasupersecretkey",
|
||||
"TF_CLI_CONFIG_FILE": filepath.Join(repoRoot, "test", ".terraformrc"),
|
||||
"TF_IN_AUTOMATION": "1",
|
||||
"TF_CLI_ARGS_init": "-no-color",
|
||||
"TF_CLI_ARGS_plan": "-no-color",
|
||||
|
|
@ -51,6 +50,7 @@ func TestProtectedBasic(t *testing.T) {
|
|||
RetryableTerraformErrors: util.GetRetryableTerraformErrors(),
|
||||
NoColor: true,
|
||||
Upgrade: true,
|
||||
// ExtraArgs: terraform.ExtraArgs{ Output: []string{"-json"} },
|
||||
})
|
||||
|
||||
_, err = terraform.InitAndApplyE(t, terraformOptions)
|
||||
|
|
@ -59,6 +59,10 @@ func TestProtectedBasic(t *testing.T) {
|
|||
util.TearDown(t, testDir, terraformOptions)
|
||||
t.Fatalf("Error creating file: %s", err)
|
||||
}
|
||||
_, err = terraform.OutputAllE(t, terraformOptions)
|
||||
if err != nil {
|
||||
t.Log("Output failed, moving along...")
|
||||
}
|
||||
|
||||
fileAExists, err := util.CheckFileExists(filepath.Join(testDir, "a_protected_test.txt"))
|
||||
if err != nil {
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
|
||||
package protected
|
||||
|
||||
import (
|
||||
|
|
@ -13,7 +11,7 @@ import (
|
|||
func TestProtectedProtects(t *testing.T) {
|
||||
t.Parallel()
|
||||
id := util.GetId()
|
||||
directory := "protected"
|
||||
directory := "local/protected"
|
||||
repoRoot, err := util.GetRepoRoot(t)
|
||||
if err != nil {
|
||||
t.Fatalf("Error getting git root directory: %v", err)
|
||||
|
|
@ -41,6 +39,7 @@ func TestProtectedProtects(t *testing.T) {
|
|||
EnvVars: map[string]string{
|
||||
"TF_DATA_DIR": testDir,
|
||||
"TF_FILE_HMAC_SECRET_KEY": "thisisasupersecretkey",
|
||||
"TF_CLI_CONFIG_FILE": filepath.Join(repoRoot, "test", ".terraformrc"),
|
||||
"TF_IN_AUTOMATION": "1",
|
||||
"TF_CLI_ARGS_init": "-no-color",
|
||||
"TF_CLI_ARGS_plan": "-no-color",
|
||||
|
|
@ -51,6 +50,7 @@ func TestProtectedProtects(t *testing.T) {
|
|||
RetryableTerraformErrors: util.GetRetryableTerraformErrors(),
|
||||
NoColor: true,
|
||||
Upgrade: true,
|
||||
// ExtraArgs: terraform.ExtraArgs{ Output: []string{"-json"} },
|
||||
})
|
||||
|
||||
_, err = terraform.InitAndApplyE(t, terraformOptions)
|
||||
|
|
@ -59,6 +59,10 @@ func TestProtectedProtects(t *testing.T) {
|
|||
util.TearDown(t, testDir, terraformOptions)
|
||||
t.Fatalf("Error creating file: %s", err)
|
||||
}
|
||||
_, err = terraform.OutputAllE(t, terraformOptions)
|
||||
if err != nil {
|
||||
t.Log("Output failed, moving along...")
|
||||
}
|
||||
|
||||
fileAExists, err := util.CheckFileExists(filepath.Join(testDir, "a_protected_test.txt"))
|
||||
if err != nil {
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/sh
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
|
||||
|
||||
# summarize.sh - reads report.json and prints a summary
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build generate
|
||||
|
|
@ -6,13 +5,9 @@
|
|||
package tools
|
||||
|
||||
import (
|
||||
_ "github.com/hashicorp/copywrite"
|
||||
_ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs"
|
||||
)
|
||||
|
||||
// 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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue