diff --git a/docs/data-sources/folder.md b/docs/data-sources/folder.md index ad7940f..4f4fe04 100644 --- a/docs/data-sources/folder.md +++ b/docs/data-sources/folder.md @@ -1,4 +1,13 @@ -# jenkins_folder Data Source +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "jenkins_folder Data Source - terraform-provider-jenkins" +subcategory: "" +description: |- + Get the attributes of a folder within Jenkins. + ~> The Jenkins installation that uses this resource is expected to have the Cloudbees Folders Plugin https://plugins.jenkins.io/cloudbees-folder installed in their system. +--- + +# jenkins_folder (Data Source) Get the attributes of a folder within Jenkins. @@ -6,25 +15,26 @@ Get the attributes of a folder within Jenkins. ## Example Usage -```hcl +```terraform data "jenkins_folder" "example" { - name = "folder-name" + name = "folder-name" } ``` -## Argument Reference + +## Schema -The following arguments are supported: +### Required -* `name` - (Required) The name of the folder being read. -* `folder` - (Optional) The folder namespace containing this folder. +- `name` (String) The name of the resource being read. +### Optional -## Attribute Reference +- `folder` (String) The folder namespace containing this resource. -In addition to all arguments above, the following attributes are exported: +### Read-Only -* `id` - The full canonical folder path, E.G. `/job/parent`. -* `description` - A block of text describing the folder's purpose. -* `display_name` - The name of the folder that is displayed in the UI. -* `template` - A Jenkins-compatible XML template to describe the folder. +- `description` (String) The description of this folder's purpose. +- `display_name` (String) The name of the folder to display in the UI. +- `id` (String) The full canonical job path, e.g. `/job/job-name` +- `template` (String) The configuration file template, used to communicate with Jenkins. diff --git a/examples/data-sources/jenkins_folder/data-source.tf b/examples/data-sources/jenkins_folder/data-source.tf new file mode 100644 index 0000000..c33f909 --- /dev/null +++ b/examples/data-sources/jenkins_folder/data-source.tf @@ -0,0 +1,3 @@ +data "jenkins_folder" "example" { + name = "folder-name" +} diff --git a/jenkins/data_source_jenkins_folder.go b/jenkins/data_source_jenkins_folder.go index 994131f..e6546aa 100644 --- a/jenkins/data_source_jenkins_folder.go +++ b/jenkins/data_source_jenkins_folder.go @@ -2,72 +2,122 @@ package jenkins import ( "context" + "strings" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" ) -func dataSourceJenkinsFolder() *schema.Resource { - return &schema.Resource{ - ReadContext: dataSourceJenkinsFolderRead, - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "The unique name of the JenkinsCI folder.", - Required: true, - ValidateDiagFunc: validateJobName, - }, - "display_name": { - Type: schema.TypeString, - Description: "The name of the folder to display in the UI.", - Computed: true, - }, - "folder": { - Type: schema.TypeString, - Description: "The folder namespace that the folder exists in.", - Optional: true, - ValidateDiagFunc: validateFolderName, - }, - "description": { - Type: schema.TypeString, - Description: "The description of this folder's purpose.", - Computed: true, +type folderDataSourceModel struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Folder types.String `tfsdk:"folder"` + Description types.String `tfsdk:"description"` + DisplayName types.String `tfsdk:"display_name"` + Template types.String `tfsdk:"template"` +} + +type folderDataSource struct { + *dataSourceHelper +} + +// Ensure the implementation satisfies the desired interfaces. +var _ datasource.DataSourceWithConfigure = &folderDataSource{} + +func newFolderDataSource() datasource.DataSource { + return &folderDataSource{ + dataSourceHelper: newDataSourceHelper(), + } +} + +func (d *folderDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_folder" +} + +func (d *folderDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: ` +Get the attributes of a folder within Jenkins. + +~> The Jenkins installation that uses this resource is expected to have the [Cloudbees Folders Plugin](https://plugins.jenkins.io/cloudbees-folder) installed in their system.`, + Attributes: d.schema(map[string]schema.Attribute{ + "display_name": schema.StringAttribute{ + MarkdownDescription: "The name of the folder to display in the UI.", + Computed: true, }, - "security": { - Type: schema.TypeSet, - Description: "The Jenkins project-based security configuration.", - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "inheritance_strategy": { - Type: schema.TypeString, - Description: "The strategy for applying these permissions sets to existing inherited permissions.", - Computed: true, - }, - "permissions": { - Type: schema.TypeList, - Computed: true, - Description: "The Jenkins permissions sets that provide access to this folder.", - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, - }, - }, + "description": schema.StringAttribute{ + MarkdownDescription: "The description of this folder's purpose.", + Computed: true, }, - "template": { - Type: schema.TypeString, - Description: "The configuration file template, used to communicate with Jenkins.", - Computed: true, + "template": schema.StringAttribute{ + MarkdownDescription: "The configuration file template, used to communicate with Jenkins.", + Computed: true, }, - }, + }), } } -func dataSourceJenkinsFolderRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - name := d.Get("name").(string) - folderName := d.Get("folder").(string) - d.SetId(formatFolderName(folderName + "/" + name)) +func (d *folderDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data folderDataSourceModel + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + name := data.Name.ValueString() + folderName := data.Folder.ValueString() + name, folders := parseCanonicalJobID(formatFolderName(folderName + "/" + name)) + job, err := d.client.GetJob(ctx, name, folders...) + if err != nil { + if strings.HasPrefix(err.Error(), "404") { + // Job does not exist + resp.State.RemoveResource(ctx) + return + } + + resp.Diagnostics.AddError( + "Unable to Read Data Source", + "An unexpected error occurred while parsing the data source read response. "+ + "Please report this issue to the provider developers.\n\n"+ + "Error: "+err.Error(), + ) + return + } + + // Extract the raw XML configuration + config, err := job.GetConfig(ctx) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Read Data Source", + "An unexpected error occurred while extracting the job configuration. "+ + "Please report this issue to the provider developers.\n\n"+ + "Error: "+err.Error(), + ) + return + } + + // Next, parse the properties from the config + f, err := parseFolder(config) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Read Folder", + "An unexpected error occurred while parsing the folder configuration. "+ + "Please report this issue to the provider developers.\n\n"+ + "Error: "+err.Error(), + ) + return + } + + data.ID = types.StringValue(job.Base) + data.Name = types.StringValue(name) + data.DisplayName = types.StringValue(f.DisplayName) + data.Folder = types.StringValue(formatFolderID(folders)) + data.Description = types.StringValue(f.Description) + data.Template = types.StringValue(strings.TrimSpace(config)) - return resourceJenkinsFolderRead(ctx, d, meta) + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } diff --git a/jenkins/provider.go b/jenkins/provider.go index 335a7b7..7b8ad8a 100644 --- a/jenkins/provider.go +++ b/jenkins/provider.go @@ -43,9 +43,7 @@ func Provider() *schema.Provider { }, }, - DataSourcesMap: map[string]*schema.Resource{ - "jenkins_folder": dataSourceJenkinsFolder(), - }, + DataSourcesMap: map[string]*schema.Resource{}, ResourcesMap: map[string]*schema.Resource{ "jenkins_folder": resourceJenkinsFolder(), diff --git a/jenkins/provider_framework.go b/jenkins/provider_framework.go index 72fa73c..61dde18 100644 --- a/jenkins/provider_framework.go +++ b/jenkins/provider_framework.go @@ -126,6 +126,7 @@ func (p *JenkinsProvider) DataSources(ctx context.Context) []func() datasource.D newCredentialVaultAppRoleDataSource, newViewDataSource, newJobDataSource, + newFolderDataSource, } } diff --git a/templates/data-sources/folder.md.tmpl b/templates/data-sources/folder.md.tmpl deleted file mode 100644 index ad7940f..0000000 --- a/templates/data-sources/folder.md.tmpl +++ /dev/null @@ -1,30 +0,0 @@ -# jenkins_folder Data Source - -Get the attributes of a folder within Jenkins. - -~> The Jenkins installation that uses this resource is expected to have the [Cloudbees Folders Plugin](https://plugins.jenkins.io/cloudbees-folder) installed in their system. - -## Example Usage - -```hcl -data "jenkins_folder" "example" { - name = "folder-name" -} -``` - -## Argument Reference - -The following arguments are supported: - -* `name` - (Required) The name of the folder being read. -* `folder` - (Optional) The folder namespace containing this folder. - - -## Attribute Reference - -In addition to all arguments above, the following attributes are exported: - -* `id` - The full canonical folder path, E.G. `/job/parent`. -* `description` - A block of text describing the folder's purpose. -* `display_name` - The name of the folder that is displayed in the UI. -* `template` - A Jenkins-compatible XML template to describe the folder.