Skip to content

Commit

Permalink
Migrate Username credential to Plugin Framework (#145)
Browse files Browse the repository at this point in the history
* Migrate Username credential to Plugin Framework

* Update generated documentation
  • Loading branch information
taiidani authored Jul 16, 2023
1 parent 5691ff4 commit 7189fb2
Show file tree
Hide file tree
Showing 12 changed files with 429 additions and 245 deletions.
39 changes: 25 additions & 14 deletions docs/data-sources/credential_username.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
# jenkins_credential_username Data Source
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "jenkins_credential_username Data Source - terraform-provider-jenkins"
subcategory: ""
description: |-
Get the attributes of a username credential within Jenkins.
---

# jenkins_credential_username (Data Source)

Get the attributes of a username credential within Jenkins.

## Example Usage

```hcl
```terraform
data "jenkins_credential_username" "example" {
name = "job-name"
name = "name"
folder = jenkins_folder.example.id
}
```

## Argument Reference
<!-- schema generated by tfplugindocs -->
## Schema

### Required

The following arguments are supported:
- `name` (String) The name of the resource being read.

* `name` - (Required) The name of the resource being read.
* `domain` - (Optional) The domain store to place the credentials into. If not set will default to the global credentials store.
* `folder` - (Optional) The folder namespace containing this resource.
### Optional

## Attribute Reference
- `domain` (String) The domain store containing this resource.
- `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 job path, E.G. `/job/job-name`.
* `description` - A human readable description of the credentials being stored.
* `scope` - The visibility of the credentials to Jenkins agents. This must be set to either "GLOBAL" or "SYSTEM".
* `username` - The username to be associated with the credentials.
- `description` (String) A human readable description of the credentials being stored.
- `id` (String) The full canonical job path, e.g. `/job/job-name`
- `scope` (String) The visibility of the credentials to Jenkins agents. This will be either "GLOBAL" or "SYSTEM".
- `username` (String) The username associated with the credentials.
42 changes: 28 additions & 14 deletions docs/resources/credential_username.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,45 @@
# jenkins_credential_username Resource
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "jenkins_credential_username Resource - terraform-provider-jenkins"
subcategory: ""
description: |-
Manages a username credential within Jenkins. This username may then be referenced within jobs that are created.
~> The "password" property may leave plain-text passwords in your state file. If using the property to manage the password in Terraform, ensure that your state file is properly secured and encrypted at rest.
---

# jenkins_credential_username (Resource)

Manages a username credential within Jenkins. This username may then be referenced within jobs that are created.

~> The "password" property may leave plain-text passwords in your state file. If using the property to manage the password in Terraform, ensure that your state file is properly secured and encrypted at rest.

## Example Usage

```hcl
```terraform
resource "jenkins_credential_username" "example" {
name = "example-username"
name = "name"
folder = jenkins_folder.example.id
username = "example"
password = "super-secret"
}
```

## Argument Reference
<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) The name of the credentials being created. This maps to the ID property within Jenkins, and cannot be changed once set.
- `username` (String) The username to be associated with the credentials.

The following arguments are supported:
### Optional

* `name` - (Required) The name of the credentials being created. This maps to the ID property within Jenkins, and cannot be changed once set.
* `domain` - (Optional) The domain store to place the credentials into. If not set will default to the global credentials store.
* `folder` - (Optional) The folder namespace to store the credentials in. If not set will default to global Jenkins credentials.
* `scope` - (Optional) The visibility of the credentials to Jenkins agents. This must be set to either "GLOBAL" or "SYSTEM". If not set will default to "GLOBAL".
* `description` - (Optional) A human readable description of the credentials being stored.
* `username` - (Required) The username to be associated with the credentials.
* `password` - (Optional) The password to be associated with the credentials. If empty then the password property will become unmanaged and expected to be set manually within Jenkins. If set then the password will be updated only upon changes -- if the password is set manually within Jenkins then it will not reconcile this drift until the next time the password property is changed.
- `description` (String) A human readable description of the credentials being stored.
- `domain` (String) The domain store to place the credentials into. If not set will default to the global credentials store.
- `folder` (String) The folder namespace to store the credentials in. If not set will default to global Jenkins credentials.
- `password` (String, Sensitive) The password to be associated with the credentials. If empty then the password property will become unmanaged and expected to be set manually within Jenkins. If set then the password will be updated only upon changes -- if the password is set manually within Jenkins then it will not reconcile this drift until the next time the password property is changed.

## Attribute Reference
### Read-Only

All arguments above are exported.
- `id` (String) The full canonical job path, e.g. `/job/job-name`
- `scope` (String) The visibility of the credentials to Jenkins agents. This must be set to either "GLOBAL" or "SYSTEM". If not set will default to "GLOBAL".
6 changes: 6 additions & 0 deletions examples/resources/jenkins_credential_username/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
resource "jenkins_credential_username" "example" {
name = "name"
folder = jenkins_folder.example.id
username = "example"
password = "super-secret"
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/bndr/gojenkins v1.1.1-0.20210407143218-9e2483ff7ebd
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/terraform-plugin-framework v1.3.2
github.com/hashicorp/terraform-plugin-framework-validators v0.10.0
github.com/hashicorp/terraform-plugin-go v0.18.0
github.com/hashicorp/terraform-plugin-mux v0.11.2
github.com/hashicorp/terraform-plugin-sdk/v2 v2.27.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ github.com/hashicorp/terraform-json v0.17.0 h1:EiA1Wp07nknYQAiv+jIt4dX4Cq5crgP+T
github.com/hashicorp/terraform-json v0.17.0/go.mod h1:Huy6zt6euxaY9knPAFKjUITn8QxUFIe9VuSzb4zn/0o=
github.com/hashicorp/terraform-plugin-framework v1.3.2 h1:aQ6GSD0CTnvoALEWvKAkcH/d8jqSE0Qq56NYEhCexUs=
github.com/hashicorp/terraform-plugin-framework v1.3.2/go.mod h1:oimsRAPJOYkZ4kY6xIGfR0PHjpHLDLaknzuptl6AvnY=
github.com/hashicorp/terraform-plugin-framework-validators v0.10.0 h1:4L0tmy/8esP6OcvocVymw52lY0HyQ5OxB7VNl7k4bS0=
github.com/hashicorp/terraform-plugin-framework-validators v0.10.0/go.mod h1:qdQJCdimB9JeX2YwOpItEu+IrfoJjWQ5PhLpAOMDQAE=
github.com/hashicorp/terraform-plugin-go v0.18.0 h1:IwTkOS9cOW1ehLd/rG0y+u/TGLK9y6fGoBjXVUquzpE=
github.com/hashicorp/terraform-plugin-go v0.18.0/go.mod h1:l7VK+2u5Kf2y+A+742GX0ouLut3gttudmvMgN0PA74Y=
github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0=
Expand Down
142 changes: 107 additions & 35 deletions jenkins/data_source_jenkins_credential_username.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,125 @@ package jenkins

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
jenkins "github.com/bndr/gojenkins"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)

func dataSourceJenkinsCredentialUsername() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceJenkinsCredentialUsernameRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Description: "The identifier assigned to the credentials.",
Required: true,
type credentialUsernameDataSourceModel struct {
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Domain types.String `tfsdk:"domain"`
Folder types.String `tfsdk:"folder"`
Scope types.String `tfsdk:"scope"`
Description types.String `tfsdk:"description"`
Username types.String `tfsdk:"username"`
}

type credentialUsernameDataSource struct {
client *jenkinsAdapter
}

// Ensure the implementation satisfies the desired interfaces.
var _ datasource.DataSourceWithConfigure = &credentialUsernameDataSource{}

func newCredentialUsernameDataSource() datasource.DataSource {
return &credentialUsernameDataSource{}
}

func (d *credentialUsernameDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_credential_username"
}

// Configure should register the client for the resource.
func (d *credentialUsernameDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}

client, ok := req.ProviderData.(*jenkinsAdapter)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Resource Configure Type",
fmt.Sprintf("Expected *jenkinsAdapter, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)

return
}

d.client = client
}

func (d *credentialUsernameDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: "Get the attributes of a username credential within Jenkins.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
MarkdownDescription: "The full canonical job path, e.g. `/job/job-name`",
},
"name": schema.StringAttribute{
Required: true,
MarkdownDescription: "The name of the resource being read.",
},
"domain": {
Type: schema.TypeString,
Description: "The domain namespace that the credentials will be added to.",
Optional: true,
"domain": schema.StringAttribute{
MarkdownDescription: "The domain store containing this resource.",
Optional: true,
},
"folder": {
Type: schema.TypeString,
Description: "The folder namespace that the credentials will be added to.",
Optional: true,
"folder": schema.StringAttribute{
MarkdownDescription: "The folder namespace containing this resource.",
Optional: true,
},
"scope": {
Type: schema.TypeString,
Description: "The Jenkins scope assigned to the credentials.",
Computed: true,
"scope": schema.StringAttribute{
MarkdownDescription: `The visibility of the credentials to Jenkins agents. This will be either "GLOBAL" or "SYSTEM".`,
Computed: true,
},
"description": {
Type: schema.TypeString,
Description: "The credentials descriptive text.",
Computed: true,
"description": schema.StringAttribute{
MarkdownDescription: "A human readable description of the credentials being stored.",
Computed: true,
},
"username": {
Type: schema.TypeString,
Description: "The credentials user username.",
Computed: true,
"username": schema.StringAttribute{
MarkdownDescription: "The username associated with the credentials.",
Computed: true,
},
},
}
}

func dataSourceJenkinsCredentialUsernameRead(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 *credentialUsernameDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data credentialUsernameDataSourceModel

// Read Terraform configuration data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

cm := d.client.Credentials()
cm.Folder = formatFolderName(data.Folder.ValueString())

cred := jenkins.UsernameCredentials{}
err := cm.GetSingle(ctx, data.Domain.ValueString(), data.Name.ValueString(), &cred)
if err != nil {
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
}

data.ID = types.StringValue(generateCredentialID(data.Folder.ValueString(), cred.ID))
data.Scope = types.StringValue(cred.Scope)
data.Description = types.StringValue(cred.Description)
data.Username = types.StringValue(cred.Username)

return resourceJenkinsCredentialUsernameRead(ctx, d, meta)
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
2 changes: 0 additions & 2 deletions jenkins/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ func Provider() *schema.Provider {
},

DataSourcesMap: map[string]*schema.Resource{
"jenkins_credential_username": dataSourceJenkinsCredentialUsername(),
"jenkins_credential_vault_approle": dataSourceJenkinsCredentialVaultAppRole(),
"jenkins_folder": dataSourceJenkinsFolder(),
"jenkins_job": dataSourceJenkinsJob(),
Expand All @@ -47,7 +46,6 @@ func Provider() *schema.Provider {
"jenkins_credential_secret_file": resourceJenkinsCredentialSecretFile(),
"jenkins_credential_secret_text": resourceJenkinsCredentialSecretText(),
"jenkins_credential_ssh": resourceJenkinsCredentialSSH(),
"jenkins_credential_username": resourceJenkinsCredentialUsername(),
"jenkins_credential_vault_approle": resourceJenkinsCredentialVaultAppRole(),
"jenkins_folder": resourceJenkinsFolder(),
"jenkins_job": resourceJenkinsJob(),
Expand Down
8 changes: 6 additions & 2 deletions jenkins/provider_framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,14 @@ func (p *JenkinsProvider) Configure(ctx context.Context, req provider.ConfigureR

// DataSources satisfies the provider.Provider interface for JenkinsProvider.
func (p *JenkinsProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{}
return []func() datasource.DataSource{
newCredentialUsernameDataSource,
}
}

// Resources satisfies the provider.Provider interface for JenkinsProvider.
func (p *JenkinsProvider) Resources(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource{}
return []func() resource.Resource{
newCredentialUsernameResource,
}
}
Loading

0 comments on commit 7189fb2

Please sign in to comment.