-
Notifications
You must be signed in to change notification settings - Fork 71
function/direxists
: Add function that checks if a directory exists
#285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
1614db3
move local_file to test directory
austinvalle 8a9c70e
add initial implementation
austinvalle 9a226cc
add changelog
austinvalle 0a2a4c3
add license headers
austinvalle 80c788a
fixed to skipbelow and added symlink test
austinvalle d993daa
resolve to absolute path
austinvalle bcd4280
generated docs
austinvalle 0fd4d33
Merge branch 'main' into av/direxists
austinvalle b67a7d1
update to use new function errors
austinvalle b4eb056
Merge branch 'main' into av/direxists
austinvalle 77cc03b
update workflow, tests, and add an example
austinvalle 9c98a52
update to use beta release
austinvalle 782da26
add template with pathexpands example
austinvalle 275e921
remove special mode
austinvalle File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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) | ||
austinvalle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 hidden or 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 hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.