-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
function/direxists
: Add function that checks if a directory exists (#…
…285) * move local_file to test directory * add initial implementation * add changelog * add license headers * fixed to skipbelow and added symlink test * resolve to absolute path * generated docs * update to use new function errors * update workflow, tests, and add an example * update to use beta release * add template with pathexpands example * remove special mode
- Loading branch information
1 parent
5712e33
commit f15ab07
Showing
24 changed files
with
387 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
kind: FEATURES | ||
body: 'functions/direxists: Added a new `direxists` function that checks for the existence | ||
of a directory, similar to the built-in `fileexists` function.' | ||
time: 2024-01-16T18:06:27.665639-05:00 | ||
custom: | ||
Issue: "285" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
page_title: "direxists function - terraform-provider-local" | ||
subcategory: "" | ||
description: |- | ||
Determines whether a directory exists at a given path. | ||
--- | ||
|
||
# function: direxists | ||
|
||
Given a path string, will return true if the directory exists. This function works only with directories. If used with a file, the function will return an error. | ||
|
||
This function behaves similar to the built-in [`fileexists`](https://developer.hashicorp.com/terraform/language/functions/fileexists) function, however, `direxists` will not replace filesystem paths including `~` with the current user's home directory path. This functionality can be achieved by using the built-in [`pathexpand`](https://developer.hashicorp.com/terraform/language/functions/pathexpand) function with `direxists`, see example below. | ||
|
||
## Example Usage | ||
|
||
### Basic Usage | ||
|
||
```terraform | ||
# Configuration using provider functions must include required_providers configuration. | ||
terraform { | ||
required_providers { | ||
local = { | ||
source = "hashicorp/local" | ||
# Setting the provider version is a strongly recommended practice | ||
# version = "..." | ||
} | ||
} | ||
# Provider functions require Terraform 1.8 and later. | ||
required_version = ">= 1.8.0" | ||
} | ||
output "example_output" { | ||
value = provider::local::direxists("${path.module}/example-directory") | ||
} | ||
``` | ||
|
||
### Usage with home directory | ||
|
||
```terraform | ||
# Configuration using provider functions must include required_providers configuration. | ||
terraform { | ||
required_providers { | ||
local = { | ||
source = "hashicorp/local" | ||
# Setting the provider version is a strongly recommended practice | ||
# version = "..." | ||
} | ||
} | ||
# Provider functions require Terraform 1.8 and later. | ||
required_version = ">= 1.8.0" | ||
} | ||
output "example_output_homedir" { | ||
value = provider::local::direxists(pathexpand("~/.ssh")) | ||
} | ||
``` | ||
|
||
## Signature | ||
|
||
<!-- signature generated by tfplugindocs --> | ||
```text | ||
direxists(path string) bool | ||
``` | ||
|
||
## Arguments | ||
|
||
<!-- arguments generated by tfplugindocs --> | ||
1. `path` (String) Relative or absolute path to check for the existence of a directory |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Configuration using provider functions must include required_providers configuration. | ||
terraform { | ||
required_providers { | ||
local = { | ||
source = "hashicorp/local" | ||
# Setting the provider version is a strongly recommended practice | ||
# version = "..." | ||
} | ||
} | ||
# Provider functions require Terraform 1.8 and later. | ||
required_version = ">= 1.8.0" | ||
} | ||
|
||
output "example_output" { | ||
value = provider::local::direxists("${path.module}/example-directory") | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Configuration using provider functions must include required_providers configuration. | ||
terraform { | ||
required_providers { | ||
local = { | ||
source = "hashicorp/local" | ||
# Setting the provider version is a strongly recommended practice | ||
# version = "..." | ||
} | ||
} | ||
# Provider functions require Terraform 1.8 and later. | ||
required_version = ">= 1.8.0" | ||
} | ||
|
||
output "example_output_homedir" { | ||
value = provider::local::direxists(pathexpand("~/.ssh")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package provider | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/function" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
) | ||
|
||
var _ function.Function = &DirectoryExistsFunction{} | ||
|
||
type DirectoryExistsFunction struct{} | ||
|
||
func NewDirectoryExistsFunction() function.Function { | ||
return &DirectoryExistsFunction{} | ||
} | ||
|
||
func (f *DirectoryExistsFunction) Metadata(ctx context.Context, req function.MetadataRequest, resp *function.MetadataResponse) { | ||
resp.Name = "direxists" | ||
} | ||
|
||
func (f *DirectoryExistsFunction) Definition(ctx context.Context, req function.DefinitionRequest, resp *function.DefinitionResponse) { | ||
resp.Definition = function.Definition{ | ||
Summary: "Determines whether a directory exists at a given path.", | ||
Description: "Given a path string, will return true if the directory exists. " + | ||
"This function works only with directories. If used with a file, the function will return an error.\n\n" + | ||
"This function behaves similar to the built-in [`fileexists`](https://developer.hashicorp.com/terraform/language/functions/fileexists) function, " + | ||
"however, `direxists` will not replace filesystem paths including `~` with the current user's home directory path. This functionality can be achieved by using the built-in " + | ||
"[`pathexpand`](https://developer.hashicorp.com/terraform/language/functions/pathexpand) function with `direxists`, see example below.", | ||
|
||
Parameters: []function.Parameter{ | ||
function.StringParameter{ | ||
Name: "path", | ||
Description: "Relative or absolute path to check for the existence of a directory", | ||
}, | ||
}, | ||
Return: function.BoolReturn{}, | ||
} | ||
} | ||
|
||
func (f *DirectoryExistsFunction) Run(ctx context.Context, req function.RunRequest, resp *function.RunResponse) { | ||
var inputPath string | ||
|
||
resp.Error = req.Arguments.Get(ctx, &inputPath) | ||
if resp.Error != nil { | ||
return | ||
} | ||
|
||
directoryPath := inputPath | ||
if !filepath.IsAbs(directoryPath) { | ||
var err error | ||
directoryPath, err = filepath.Abs(directoryPath) | ||
if err != nil { | ||
resp.Error = function.NewArgumentFuncError(0, fmt.Sprintf("Error expanding relative path to absolute path: %s", err)) | ||
return | ||
} | ||
} | ||
|
||
directoryPath = filepath.Clean(directoryPath) | ||
|
||
fi, err := os.Stat(directoryPath) | ||
if err != nil { | ||
if os.IsNotExist(err) { | ||
resp.Error = resp.Result.Set(ctx, types.BoolValue(false)) | ||
return | ||
} else { | ||
resp.Error = function.NewArgumentFuncError(0, fmt.Sprintf("Error checking for directory: %s", err)) | ||
return | ||
} | ||
} | ||
|
||
if fi.IsDir() { | ||
resp.Error = resp.Result.Set(ctx, types.BoolValue(true)) | ||
return | ||
} | ||
resp.Error = function.NewArgumentFuncError(0, fmt.Sprintf("Invalid file mode detected: %q was found, but is not a directory", inputPath)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package provider | ||
|
||
import ( | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/hashicorp/go-version" | ||
"github.com/hashicorp/terraform-plugin-testing/config" | ||
"github.com/hashicorp/terraform-plugin-testing/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-testing/knownvalue" | ||
"github.com/hashicorp/terraform-plugin-testing/plancheck" | ||
"github.com/hashicorp/terraform-plugin-testing/tfversion" | ||
) | ||
|
||
func TestDirectoryExists_basic(t *testing.T) { | ||
resource.UnitTest(t, resource.TestCase{ | ||
TerraformVersionChecks: []tfversion.TerraformVersionCheck{ | ||
// TODO: Replace with the stable v1.8.0 release when available | ||
tfversion.SkipBelow(version.Must(version.NewVersion("v1.8.0-beta1"))), | ||
}, | ||
ProtoV5ProviderFactories: protoV5ProviderFactories(), | ||
Steps: []resource.TestStep{ | ||
{ | ||
ConfigDirectory: config.TestNameDirectory(), | ||
ConfigPlanChecks: resource.ConfigPlanChecks{ | ||
PreApply: []plancheck.PlanCheck{ | ||
plancheck.ExpectKnownOutputValue("test_dir_exists", knownvalue.Bool(true)), | ||
plancheck.ExpectKnownOutputValue("test_dir_doesnt_exist", knownvalue.Bool(false)), | ||
}, | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestDirectoryExists_invalid_file(t *testing.T) { | ||
resource.UnitTest(t, resource.TestCase{ | ||
TerraformVersionChecks: []tfversion.TerraformVersionCheck{ | ||
// TODO: Replace with the stable v1.8.0 release when available | ||
tfversion.SkipBelow(version.Must(version.NewVersion("v1.8.0-beta1"))), | ||
}, | ||
ProtoV5ProviderFactories: protoV5ProviderFactories(), | ||
Steps: []resource.TestStep{ | ||
{ | ||
ConfigDirectory: config.TestNameDirectory(), | ||
ExpectError: regexp.MustCompile("\"./testdata/TestDirectoryExists_invalid_file/not_a_dir.txt\" was found, but is\nnot a directory."), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestDirectoryExists_invalid_symlink(t *testing.T) { | ||
resource.UnitTest(t, resource.TestCase{ | ||
TerraformVersionChecks: []tfversion.TerraformVersionCheck{ | ||
// TODO: Replace with the stable v1.8.0 release when available | ||
tfversion.SkipBelow(version.Must(version.NewVersion("v1.8.0-beta1"))), | ||
}, | ||
ProtoV5ProviderFactories: protoV5ProviderFactories(), | ||
Steps: []resource.TestStep{ | ||
{ | ||
ConfigDirectory: config.TestNameDirectory(), | ||
ExpectError: regexp.MustCompile("\"./testdata/TestDirectoryExists_invalid_symlink/not_a_dir_symlink\" was found,\nbut is not a directory."), | ||
}, | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.