Skip to content

Commit fcda2d9

Browse files
committed
Moving validators to set, updating descriptions, adding config validators (#112)
1 parent 20773a8 commit fcda2d9

File tree

5 files changed

+133
-66
lines changed

5 files changed

+133
-66
lines changed

internal/provider/data_source_archive_file.go

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"os"
1212
"path"
1313

14+
"github.com/hashicorp/terraform-plugin-framework-validators/datasourcevalidator"
1415
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
1516
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1617
"github.com/hashicorp/terraform-plugin-framework/datasource"
@@ -28,32 +29,45 @@ func NewArchiveFileDataSource() datasource.DataSource {
2829

2930
type archiveFileDataSource struct{}
3031

32+
func (d *archiveFileDataSource) ConfigValidators(context.Context) []datasource.ConfigValidator {
33+
return []datasource.ConfigValidator{
34+
datasourcevalidator.AtLeastOneOf(
35+
fwpath.MatchRoot("source"),
36+
fwpath.MatchRoot("source_content_filename"),
37+
fwpath.MatchRoot("source_file"),
38+
fwpath.MatchRoot("source_dir"),
39+
),
40+
}
41+
}
42+
3143
func (d *archiveFileDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
3244
resp.Schema = schema.Schema{
3345
Description: "Generates an archive from content, a file, or directory of files.",
3446
Blocks: map[string]schema.Block{
3547
"source": schema.SetNestedBlock{
36-
Description: "Specifies attributes of a single source file to include into the archive.",
48+
Description: "Specifies attributes of a single source file to include into the archive. " +
49+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
50+
"or `source_dir` must be specified.",
3751
NestedObject: schema.NestedBlockObject{
3852
Attributes: map[string]schema.Attribute{
3953
"content": schema.StringAttribute{
4054
Description: "Add this content to the archive with `filename` as the filename.",
4155
Required: true,
42-
Validators: []validator.String{
43-
stringvalidator.ConflictsWith(
44-
fwpath.MatchRoot("source_file"),
45-
fwpath.MatchRoot("source_dir"),
46-
fwpath.MatchRoot("source_content"),
47-
fwpath.MatchRoot("source_content_filename"),
48-
),
49-
},
5056
},
5157
"filename": schema.StringAttribute{
5258
Description: "Set this as the filename when declaring a `source`.",
5359
Required: true,
5460
},
5561
},
5662
},
63+
Validators: []validator.Set{
64+
setvalidator.ConflictsWith(
65+
fwpath.MatchRoot("source_file"),
66+
fwpath.MatchRoot("source_dir"),
67+
fwpath.MatchRoot("source_content"),
68+
fwpath.MatchRoot("source_content_filename"),
69+
),
70+
},
5771
},
5872
},
5973
Attributes: map[string]schema.Attribute{
@@ -66,8 +80,10 @@ func (d *archiveFileDataSource) Schema(ctx context.Context, req datasource.Schem
6680
Required: true,
6781
},
6882
"source_content": schema.StringAttribute{
69-
Description: "Add only this content to the archive with `source_content_filename` as the filename.",
70-
Optional: true,
83+
Description: "Add only this content to the archive with `source_content_filename` as the filename. " +
84+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
85+
"or `source_dir` must be specified.",
86+
Optional: true,
7187
Validators: []validator.String{
7288
stringvalidator.ConflictsWith(
7389
fwpath.MatchRoot("source_file"),
@@ -76,8 +92,10 @@ func (d *archiveFileDataSource) Schema(ctx context.Context, req datasource.Schem
7692
},
7793
},
7894
"source_content_filename": schema.StringAttribute{
79-
Description: "Set this as the filename when using `source_content`.",
80-
Optional: true,
95+
Description: "Set this as the filename when using `source_content`. " +
96+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
97+
"or `source_dir` must be specified.",
98+
Optional: true,
8199
Validators: []validator.String{
82100
stringvalidator.ConflictsWith(
83101
fwpath.MatchRoot("source_file"),
@@ -86,8 +104,10 @@ func (d *archiveFileDataSource) Schema(ctx context.Context, req datasource.Schem
86104
},
87105
},
88106
"source_file": schema.StringAttribute{
89-
Description: "Package this file into the archive.",
90-
Optional: true,
107+
Description: "Package this file into the archive. " +
108+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
109+
"or `source_dir` must be specified.",
110+
Optional: true,
91111
Validators: []validator.String{
92112
stringvalidator.ConflictsWith(
93113
fwpath.MatchRoot("source_dir"),
@@ -97,8 +117,10 @@ func (d *archiveFileDataSource) Schema(ctx context.Context, req datasource.Schem
97117
},
98118
},
99119
"source_dir": schema.StringAttribute{
100-
Description: "Package entire contents of this directory into the archive.",
101-
Optional: true,
120+
Description: "Package entire contents of this directory into the archive. " +
121+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
122+
"or `source_dir` must be specified.",
123+
Optional: true,
102124
Validators: []validator.String{
103125
stringvalidator.ConflictsWith(
104126
fwpath.MatchRoot("source_file"),

internal/provider/data_source_archive_file_test.go

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import (
44
"fmt"
55
"os"
66
"path/filepath"
7+
"regexp"
78
"testing"
89

910
r "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
1011
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
1112
)
1213

1314
func TestAccArchiveFile_Basic(t *testing.T) {
14-
td := testTempDir(t)
15-
defer os.RemoveAll(td)
15+
td := t.TempDir()
1616

1717
f := filepath.Join(td, "zip_file_acc_test.zip")
1818

@@ -138,8 +138,7 @@ func TestDataSource_UpgradeFromVersion2_2_0_ContentConfig(t *testing.T) {
138138
}
139139

140140
func TestDataSource_UpgradeFromVersion2_2_0_FileConfig(t *testing.T) {
141-
td := testTempDir(t)
142-
defer os.RemoveAll(td)
141+
td := t.TempDir()
143142

144143
f := filepath.Join(td, "zip_file_acc_test_upgrade_file_config.zip")
145144

@@ -190,8 +189,7 @@ func TestDataSource_UpgradeFromVersion2_2_0_FileConfig(t *testing.T) {
190189
}
191190

192191
func TestDataSource_UpgradeFromVersion2_2_0_DirConfig(t *testing.T) {
193-
td := testTempDir(t)
194-
defer os.RemoveAll(td)
192+
td := t.TempDir()
195193

196194
f := filepath.Join(td, "zip_file_acc_test_upgrade_dir_config.zip")
197195

@@ -242,8 +240,7 @@ func TestDataSource_UpgradeFromVersion2_2_0_DirConfig(t *testing.T) {
242240
}
243241

244242
func TestDataSource_UpgradeFromVersion2_2_0_DirExcludesConfig(t *testing.T) {
245-
td := testTempDir(t)
246-
defer os.RemoveAll(td)
243+
td := t.TempDir()
247244

248245
f := filepath.Join(td, "zip_file_acc_test_upgrade_dir_excludes.zip")
249246

@@ -278,8 +275,7 @@ func TestDataSource_UpgradeFromVersion2_2_0_DirExcludesConfig(t *testing.T) {
278275
}
279276

280277
func TestDataSource_UpgradeFromVersion2_2_0_SourceConfig(t *testing.T) {
281-
td := testTempDir(t)
282-
defer os.RemoveAll(td)
278+
td := t.TempDir()
283279

284280
f := filepath.Join(td, "zip_file_acc_test_upgrade_source.zip")
285281

@@ -313,6 +309,18 @@ func TestDataSource_UpgradeFromVersion2_2_0_SourceConfig(t *testing.T) {
313309
})
314310
}
315311

312+
func TestAccArchiveFile_SourceConfigMissing(t *testing.T) {
313+
r.ParallelTest(t, r.TestCase{
314+
ProtoV5ProviderFactories: protoV5ProviderFactories(),
315+
Steps: []r.TestStep{
316+
{
317+
Config: testAccArchiveSourceConfigMissing(),
318+
ExpectError: regexp.MustCompile(`.*At least one of these attributes must be configured:\n\[source_content_filename,source_file,source_dir]`),
319+
},
320+
},
321+
})
322+
}
323+
316324
func testAccArchiveFileSize(filename string, fileSize *string) r.TestCheckFunc {
317325
return func(s *terraform.State) error {
318326
*fileSize = ""
@@ -386,12 +394,13 @@ data "archive_file" "foo" {
386394
`, filepath.ToSlash(outputPath))
387395
}
388396

389-
func testTempDir(t *testing.T) string {
390-
tmp, err := os.MkdirTemp("", "tf")
391-
if err != nil {
392-
t.Fatal(err)
393-
}
394-
return tmp
397+
func testAccArchiveSourceConfigMissing() string {
398+
return `
399+
data "archive_file" "foo" {
400+
type = "zip"
401+
output_path = "path"
402+
}
403+
`
395404
}
396405

397406
//nolint:unparam

internal/provider/resource_archive_file.go

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77
"path"
88

9+
"github.com/hashicorp/terraform-plugin-framework-validators/resourcevalidator"
910
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
1011
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1112
"github.com/hashicorp/terraform-plugin-framework/diag"
@@ -27,26 +28,31 @@ func NewArchiveFileResource() resource.Resource {
2728

2829
type archiveFileResource struct{}
2930

31+
func (d *archiveFileResource) ConfigValidators(context.Context) []resource.ConfigValidator {
32+
return []resource.ConfigValidator{
33+
resourcevalidator.AtLeastOneOf(
34+
fwpath.MatchRoot("source"),
35+
fwpath.MatchRoot("source_content_filename"),
36+
fwpath.MatchRoot("source_file"),
37+
fwpath.MatchRoot("source_dir"),
38+
),
39+
}
40+
}
41+
3042
func (d *archiveFileResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
3143
resp.Schema = schema.Schema{
3244
Description: `**NOTE**: This resource is deprecated, use data source instead.`,
3345
DeprecationMessage: `**NOTE**: This resource is deprecated, use data source instead.`,
3446
Blocks: map[string]schema.Block{
3547
"source": schema.SetNestedBlock{
36-
Description: "Specifies attributes of a single source file to include into the archive.",
48+
Description: "Specifies attributes of a single source file to include into the archive. " +
49+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
50+
"or `source_dir` must be specified.",
3751
NestedObject: schema.NestedBlockObject{
3852
Attributes: map[string]schema.Attribute{
3953
"content": schema.StringAttribute{
4054
Description: "Add this content to the archive with `filename` as the filename.",
4155
Required: true,
42-
Validators: []validator.String{
43-
stringvalidator.ConflictsWith(
44-
fwpath.MatchRoot("source_file"),
45-
fwpath.MatchRoot("source_dir"),
46-
fwpath.MatchRoot("source_content"),
47-
fwpath.MatchRoot("source_content_filename"),
48-
),
49-
},
5056
PlanModifiers: []planmodifier.String{
5157
stringplanmodifier.RequiresReplace(),
5258
},
@@ -60,6 +66,14 @@ func (d *archiveFileResource) Schema(ctx context.Context, req resource.SchemaReq
6066
},
6167
},
6268
},
69+
Validators: []validator.Set{
70+
setvalidator.ConflictsWith(
71+
fwpath.MatchRoot("source_file"),
72+
fwpath.MatchRoot("source_dir"),
73+
fwpath.MatchRoot("source_content"),
74+
fwpath.MatchRoot("source_content_filename"),
75+
),
76+
},
6377
},
6478
},
6579
Attributes: map[string]schema.Attribute{
@@ -75,8 +89,10 @@ func (d *archiveFileResource) Schema(ctx context.Context, req resource.SchemaReq
7589
},
7690
},
7791
"source_content": schema.StringAttribute{
78-
Description: "Add only this content to the archive with `source_content_filename` as the filename.",
79-
Optional: true,
92+
Description: "Add only this content to the archive with `source_content_filename` as the filename. " +
93+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
94+
"or `source_dir` must be specified.",
95+
Optional: true,
8096
Validators: []validator.String{
8197
stringvalidator.ConflictsWith(
8298
fwpath.MatchRoot("source_file"),
@@ -88,8 +104,10 @@ func (d *archiveFileResource) Schema(ctx context.Context, req resource.SchemaReq
88104
},
89105
},
90106
"source_content_filename": schema.StringAttribute{
91-
Description: "Set this as the filename when using `source_content`.",
92-
Optional: true,
107+
Description: "Set this as the filename when using `source_content`. " +
108+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
109+
"or `source_dir` must be specified.",
110+
Optional: true,
93111
Validators: []validator.String{
94112
stringvalidator.ConflictsWith(
95113
fwpath.MatchRoot("source_file"),
@@ -101,8 +119,10 @@ func (d *archiveFileResource) Schema(ctx context.Context, req resource.SchemaReq
101119
},
102120
},
103121
"source_file": schema.StringAttribute{
104-
Description: "Package this file into the archive.",
105-
Optional: true,
122+
Description: "Package this file into the archive. " +
123+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
124+
"or `source_dir` must be specified.",
125+
Optional: true,
106126
Validators: []validator.String{
107127
stringvalidator.ConflictsWith(
108128
fwpath.MatchRoot("source_dir"),
@@ -115,8 +135,10 @@ func (d *archiveFileResource) Schema(ctx context.Context, req resource.SchemaReq
115135
},
116136
},
117137
"source_dir": schema.StringAttribute{
118-
Description: "Package entire contents of this directory into the archive.",
119-
Optional: true,
138+
Description: "Package entire contents of this directory into the archive. " +
139+
"One and only one of `source`, `source_content_filename` (with `source_content`), `source_file`, " +
140+
"or `source_dir` must be specified.",
141+
Optional: true,
120142
Validators: []validator.String{
121143
stringvalidator.ConflictsWith(
122144
fwpath.MatchRoot("source_file"),

0 commit comments

Comments
 (0)