From 8e6e5a33ebe1401a4ace9a5f49afe6bb8a996d9f Mon Sep 17 00:00:00 2001 From: Maxime Lagresle Date: Sat, 20 Apr 2024 10:33:34 +0200 Subject: [PATCH] add support for data folder --- docs/data-sources/folder.md | 27 +++++++ docs/resources/folder.md | 5 +- internal/provider/data_source.go | 13 +++- internal/provider/data_source_folder.go | 13 ++++ internal/provider/data_source_folder_test.go | 36 ++++++++++ internal/provider/data_source_item_login.go | 2 +- .../provider/data_source_item_secure_note.go | 2 +- internal/provider/provider.go | 3 +- internal/provider/resource_folder.go | 18 +---- internal/provider/schema.go | 65 ----------------- internal/provider/schema_folder.go | 50 +++++++++++++ internal/provider/schema_login.go | 70 +++++++++++++++++++ 12 files changed, 217 insertions(+), 87 deletions(-) create mode 100644 docs/data-sources/folder.md create mode 100644 internal/provider/data_source_folder.go create mode 100644 internal/provider/data_source_folder_test.go create mode 100644 internal/provider/schema_folder.go create mode 100644 internal/provider/schema_login.go diff --git a/docs/data-sources/folder.md b/docs/data-sources/folder.md new file mode 100644 index 0000000..9e92796 --- /dev/null +++ b/docs/data-sources/folder.md @@ -0,0 +1,27 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "bitwarden_folder Data Source - terraform-provider-bitwarden" +subcategory: "" +description: |- + Use this data source to get information on an existing Folder. +--- + +# bitwarden_folder (Data Source) + +Use this data source to get information on an existing Folder. + + + + +## Schema + +### Optional + +- `filter_collection_id` (String) Filter search results by collection ID +- `filter_organization_id` (String) Filter search results by organization ID +- `id` (String) Identifier. +- `search` (String) Search items matching the search string. Can be combined with filters to narrow down the search. + +### Read-Only + +- `name` (String) Name. diff --git a/docs/resources/folder.md b/docs/resources/folder.md index 9d61c94..922bf85 100644 --- a/docs/resources/folder.md +++ b/docs/resources/folder.md @@ -25,10 +25,13 @@ resource "bitwarden_folder" "cloud_credentials" { - `name` (String) Name. -### Read-Only +### Optional - `id` (String) Identifier. +### Read-Only + + ## Import Import is supported using the following syntax: diff --git a/internal/provider/data_source.go b/internal/provider/data_source.go index d5ad905..86f9e26 100644 --- a/internal/provider/data_source.go +++ b/internal/provider/data_source.go @@ -8,7 +8,7 @@ import ( "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/bw" ) -func readDataSource(attrObject bw.ObjectType, attrType bw.ItemType) schema.ReadContextFunc { +func readDataSourceItem(attrObject bw.ObjectType, attrType bw.ItemType) schema.ReadContextFunc { return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { d.SetId(d.Get(attributeID).(string)) err := d.Set(attributeObject, attrObject) @@ -22,3 +22,14 @@ func readDataSource(attrObject bw.ObjectType, attrType bw.ItemType) schema.ReadC return objectRead(ctx, d, meta) } } + +func readDataSourceFolder() schema.ReadContextFunc { + return func(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + d.SetId(d.Get(attributeID).(string)) + err := d.Set(attributeObject, bw.ObjectTypeFolder) + if err != nil { + return diag.FromErr(err) + } + return objectRead(ctx, d, meta) + } +} diff --git a/internal/provider/data_source_folder.go b/internal/provider/data_source_folder.go new file mode 100644 index 0000000..30e290f --- /dev/null +++ b/internal/provider/data_source_folder.go @@ -0,0 +1,13 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceFolder() *schema.Resource { + return &schema.Resource{ + Description: "Use this data source to get information on an existing Folder.", + ReadContext: readDataSourceFolder(), + Schema: folderSchema(DataSource), + } +} diff --git a/internal/provider/data_source_folder_test.go b/internal/provider/data_source_folder_test.go new file mode 100644 index 0000000..2c0071d --- /dev/null +++ b/internal/provider/data_source_folder_test.go @@ -0,0 +1,36 @@ +package provider + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccDataSourceFolderAttributes(t *testing.T) { + ensureVaultwardenConfigured(t) + + resourceName := "bitwarden_folder.foo" + + resource.UnitTest(t, resource.TestCase{ + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: tfConfigProvider() + tfConfigResourceFolder(), + }, + { + Config: tfConfigProvider() + tfConfigResourceFolder() + tfConfigDataFolder(), + Check: checkObject(resourceName), + }, + }, + }) +} + +func tfConfigDataFolder() string { + return ` +data "bitwarden_folder" "foo_data" { + provider = bitwarden + + search = "folder-bar" +} +` +} diff --git a/internal/provider/data_source_item_login.go b/internal/provider/data_source_item_login.go index be9caab..a2550c8 100644 --- a/internal/provider/data_source_item_login.go +++ b/internal/provider/data_source_item_login.go @@ -13,7 +13,7 @@ func dataSourceItemLogin() *schema.Resource { return &schema.Resource{ Description: "Use this data source to get information on an existing Login.", - ReadContext: readDataSource(bw.ObjectTypeItem, bw.ItemTypeLogin), + ReadContext: readDataSourceItem(bw.ObjectTypeItem, bw.ItemTypeLogin), Schema: dataSourceItemLoginSchema, } } diff --git a/internal/provider/data_source_item_secure_note.go b/internal/provider/data_source_item_secure_note.go index 8c6a979..78ee08b 100644 --- a/internal/provider/data_source_item_secure_note.go +++ b/internal/provider/data_source_item_secure_note.go @@ -10,7 +10,7 @@ func dataSourceItemSecureNote() *schema.Resource { return &schema.Resource{ Description: "Use this data source to get information on an existing Secure Note.", - ReadContext: readDataSource(bw.ObjectTypeItem, bw.ItemTypeSecureNote), + ReadContext: readDataSourceItem(bw.ObjectTypeItem, bw.ItemTypeSecureNote), Schema: dataSourceItemSecureNoteSchema, } } diff --git a/internal/provider/provider.go b/internal/provider/provider.go index f8ecb80..42c9b6b 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -92,12 +92,13 @@ func New(version string) func() *schema.Provider { }, DataSourcesMap: map[string]*schema.Resource{ "bitwarden_attachment": dataSourceAttachment(), + "bitwarden_folder": dataSourceFolder(), "bitwarden_item_login": dataSourceItemLogin(), "bitwarden_item_secure_note": dataSourceItemSecureNote(), }, ResourcesMap: map[string]*schema.Resource{ - "bitwarden_folder": resourceFolder(), "bitwarden_attachment": resourceAttachment(), + "bitwarden_folder": resourceFolder(), "bitwarden_item_login": resourceItemLogin(), "bitwarden_item_secure_note": resourceItemSecureNote(), }, diff --git a/internal/provider/resource_folder.go b/internal/provider/resource_folder.go index 6173bbd..ff06ab2 100644 --- a/internal/provider/resource_folder.go +++ b/internal/provider/resource_folder.go @@ -18,23 +18,7 @@ func resourceFolder() *schema.Resource { DeleteContext: objectDelete, Importer: importFolderResource(), - Schema: map[string]*schema.Schema{ - attributeID: { - Description: descriptionIdentifier, - Type: schema.TypeString, - Computed: true, - }, - attributeName: { - Description: descriptionName, - Type: schema.TypeString, - Required: true, - }, - attributeObject: { - Description: descriptionInternal, - Type: schema.TypeString, - Computed: true, - }, - }, + Schema: folderSchema(Resource), } } diff --git a/internal/provider/schema.go b/internal/provider/schema.go index 92824ca..bc608f5 100644 --- a/internal/provider/schema.go +++ b/internal/provider/schema.go @@ -2,7 +2,6 @@ package provider import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) type schemaTypeEnum int @@ -12,49 +11,6 @@ const ( Resource schemaTypeEnum = 1 ) -func loginSchema(schemaType schemaTypeEnum) map[string]*schema.Schema { - base := map[string]*schema.Schema{ - attributeLoginPassword: { - Description: descriptionLoginPassword, - Type: schema.TypeString, - Computed: schemaType == DataSource, - Optional: schemaType == Resource, - Sensitive: true, - }, - attributeLoginUsername: { - Description: descriptionLoginUsername, - Type: schema.TypeString, - Computed: schemaType == DataSource, - Optional: schemaType == Resource, - Sensitive: true, - }, - attributeLoginTotp: { - Description: descriptionLoginTotp, - Type: schema.TypeString, - Computed: schemaType == DataSource, - Optional: schemaType == Resource, - Sensitive: true, - }, - attributeLoginURIs: { - Description: descriptionLoginUri, - Type: schema.TypeList, - Elem: uriElem(), - Computed: schemaType == DataSource, - Optional: schemaType == Resource, - Sensitive: false, - }, - } - - if schemaType == DataSource { - base[attributeFilterURL] = &schema.Schema{ - Description: descriptionFilterURL, - Type: schema.TypeString, - Optional: true, - } - } - return base -} - func baseSchema(schemaType schemaTypeEnum) map[string]*schema.Schema { base := map[string]*schema.Schema{ @@ -220,27 +176,6 @@ func baseSchema(schemaType schemaTypeEnum) map[string]*schema.Schema { return base } -func uriElem() *schema.Resource { - validMatchStr := []string{"default", "base_domain", "host", "start_with", "exact", "regexp", "never"} - - return &schema.Resource{ - Schema: map[string]*schema.Schema{ - attributeLoginURIsMatch: { - Description: descriptionLoginUriMatch, - Type: schema.TypeString, - Default: validMatchStr[0], - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice(validMatchStr, false)), - Optional: true, - }, - attributeLoginURIsValue: { - Description: descriptionLoginUriValue, - Type: schema.TypeString, - Required: true, - }, - }, - } -} - func attachmentSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ attributeID: { diff --git a/internal/provider/schema_folder.go b/internal/provider/schema_folder.go new file mode 100644 index 0000000..107c6d2 --- /dev/null +++ b/internal/provider/schema_folder.go @@ -0,0 +1,50 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func folderSchema(schemaType schemaTypeEnum) map[string]*schema.Schema { + base := map[string]*schema.Schema{ + attributeID: { + Description: descriptionIdentifier, + Type: schema.TypeString, + Computed: schemaType == Resource, + Optional: true, + }, + attributeName: { + Description: descriptionName, + Type: schema.TypeString, + Computed: schemaType == DataSource, + Required: schemaType == Resource, + }, + attributeObject: { + Description: descriptionInternal, + Type: schema.TypeString, + Computed: true, + }, + } + + if schemaType == DataSource { + base[attributeFilterCollectionId] = &schema.Schema{ + Description: descriptionFilterCollectionID, + Type: schema.TypeString, + Optional: true, + } + + base[attributeFilterOrganizationID] = &schema.Schema{ + Description: descriptionFilterOrganizationID, + Type: schema.TypeString, + Optional: true, + } + + base[attributeFilterSearch] = &schema.Schema{ + Description: descriptionFilterSearch, + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: []string{attributeFilterSearch, attributeID}, + } + } + + return base +} diff --git a/internal/provider/schema_login.go b/internal/provider/schema_login.go new file mode 100644 index 0000000..2b08183 --- /dev/null +++ b/internal/provider/schema_login.go @@ -0,0 +1,70 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func loginSchema(schemaType schemaTypeEnum) map[string]*schema.Schema { + base := map[string]*schema.Schema{ + attributeLoginPassword: { + Description: descriptionLoginPassword, + Type: schema.TypeString, + Computed: schemaType == DataSource, + Optional: schemaType == Resource, + Sensitive: true, + }, + attributeLoginUsername: { + Description: descriptionLoginUsername, + Type: schema.TypeString, + Computed: schemaType == DataSource, + Optional: schemaType == Resource, + Sensitive: true, + }, + attributeLoginTotp: { + Description: descriptionLoginTotp, + Type: schema.TypeString, + Computed: schemaType == DataSource, + Optional: schemaType == Resource, + Sensitive: true, + }, + attributeLoginURIs: { + Description: descriptionLoginUri, + Type: schema.TypeList, + Elem: uriElem(), + Computed: schemaType == DataSource, + Optional: schemaType == Resource, + Sensitive: false, + }, + } + + if schemaType == DataSource { + base[attributeFilterURL] = &schema.Schema{ + Description: descriptionFilterURL, + Type: schema.TypeString, + Optional: true, + } + } + return base +} + +func uriElem() *schema.Resource { + validMatchStr := []string{"default", "base_domain", "host", "start_with", "exact", "regexp", "never"} + + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + attributeLoginURIsMatch: { + Description: descriptionLoginUriMatch, + Type: schema.TypeString, + Default: validMatchStr[0], + ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice(validMatchStr, false)), + Optional: true, + }, + attributeLoginURIsValue: { + Description: descriptionLoginUriValue, + Type: schema.TypeString, + Required: true, + }, + }, + } +}