Skip to content

Commit b113486

Browse files
committed
Add CA Product DataSource
1 parent 7937339 commit b113486

File tree

4 files changed

+183
-0
lines changed

4 files changed

+183
-0
lines changed

docs/data-sources/ca_product.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "tlspc_ca_product Data Source - tlspc"
4+
subcategory: ""
5+
description: |-
6+
7+
---
8+
9+
# tlspc_ca_product (Data Source)
10+
11+
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `ca_name` (String)
21+
- `product_option` (String)
22+
- `type` (String)
23+
24+
### Read-Only
25+
26+
- `id` (String) The ID of this resource.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright (c) Venafi, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package provider
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
"terraform-provider-tlspc/internal/tlspc"
11+
12+
"github.com/hashicorp/terraform-plugin-framework/datasource"
13+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
14+
"github.com/hashicorp/terraform-plugin-framework/types"
15+
)
16+
17+
// Ensure the implementation satisfies the expected interfaces.
18+
var (
19+
_ datasource.DataSource = &caProductDataSource{}
20+
_ datasource.DataSourceWithConfigure = &caProductDataSource{}
21+
)
22+
23+
// NewCoffeesDataSource is a helper function to simplify the provider implementation.
24+
func NewCAProductDataSource() datasource.DataSource {
25+
return &caProductDataSource{}
26+
}
27+
28+
// caProductDataSource is the data source implementation.
29+
type caProductDataSource struct {
30+
client *tlspc.Client
31+
}
32+
33+
// Configure adds the provider configured client to the data source.
34+
func (d *caProductDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
35+
// Add a nil check when handling ProviderData because Terraform
36+
// sets that data after it calls the ConfigureProvider RPC.
37+
if req.ProviderData == nil {
38+
return
39+
}
40+
41+
client, ok := req.ProviderData.(*tlspc.Client)
42+
if !ok {
43+
resp.Diagnostics.AddError(
44+
"Unexpected Data Source Configure Type",
45+
fmt.Sprintf("Expected *tlspc.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
46+
)
47+
48+
return
49+
}
50+
51+
d.client = client
52+
}
53+
54+
// Metadata returns the data source type name.
55+
func (d *caProductDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
56+
resp.TypeName = req.ProviderTypeName + "_ca_product"
57+
}
58+
59+
// Schema defines the schema for the data source.
60+
func (d *caProductDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
61+
resp.Schema = schema.Schema{
62+
Attributes: map[string]schema.Attribute{
63+
"id": schema.StringAttribute{
64+
Computed: true,
65+
},
66+
"type": schema.StringAttribute{
67+
Required: true,
68+
},
69+
"ca_name": schema.StringAttribute{
70+
Required: true,
71+
},
72+
"product_option": schema.StringAttribute{
73+
Required: true,
74+
},
75+
},
76+
}
77+
}
78+
79+
type caProductDataSourceModel struct {
80+
ID types.String `tfsdk:"id"`
81+
Type types.String `tfsdk:"type"`
82+
CAName types.String `tfsdk:"ca_name"`
83+
ProductOption types.String `tfsdk:"product_option"`
84+
}
85+
86+
// Read refreshes the Terraform state with the latest data.
87+
func (d *caProductDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
88+
var model caProductDataSourceModel
89+
diags := req.Config.Get(ctx, &model)
90+
resp.Diagnostics.Append(diags...)
91+
if resp.Diagnostics.HasError() {
92+
return
93+
}
94+
95+
caProduct, err := d.client.GetCAProductOption(model.Type.ValueString(), model.CAName.ValueString(), model.ProductOption.ValueString())
96+
if err != nil {
97+
resp.Diagnostics.AddError(
98+
"Error retrieving CA Product",
99+
fmt.Sprintf("Error retrieving CA Product: %s", err.Error()),
100+
)
101+
return
102+
}
103+
model.ID = types.StringValue(caProduct.ID)
104+
diags = resp.State.Set(ctx, &model)
105+
resp.Diagnostics.Append(diags...)
106+
}

internal/provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func (p *tlspcProvider) Resources(ctx context.Context) []func() resource.Resourc
9292
func (p *tlspcProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
9393
return []func() datasource.DataSource{
9494
NewUserDataSource,
95+
NewCAProductDataSource,
9596
}
9697
}
9798

internal/tlspc/tlspc.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,3 +505,53 @@ func (c *Client) DeletePlugin(id string) error {
505505

506506
return nil
507507
}
508+
509+
type CAProductOption struct {
510+
ID string `json:"id"`
511+
Name string `json:"productName"`
512+
}
513+
514+
type CAAccount struct {
515+
ID string `json:"id"`
516+
Name string `json:"key"`
517+
}
518+
519+
type caAccounts struct {
520+
Accounts []caAccount `json:"accounts"`
521+
}
522+
523+
type caAccount struct {
524+
Account CAAccount `json:"account"`
525+
ProductOptions []CAProductOption `json:"productOptions"`
526+
}
527+
528+
func (c *Client) GetCAProductOption(kind, name, option string) (*CAProductOption, error) {
529+
path := c.Path(`%s/v1/certificateauthorities/` + kind + "/accounts")
530+
531+
resp, err := c.Get(path)
532+
if err != nil {
533+
return nil, fmt.Errorf("Error getting user: %s", err)
534+
}
535+
body, err := io.ReadAll(resp.Body)
536+
if err != nil {
537+
return nil, fmt.Errorf("Error reading response body: %s", err)
538+
}
539+
var accounts caAccounts
540+
err = json.Unmarshal(body, &accounts)
541+
if err != nil {
542+
return nil, fmt.Errorf("Error decoding response: %s", string(body))
543+
}
544+
for _, acc := range accounts.Accounts {
545+
acct := acc.Account
546+
if acct.Name != name {
547+
continue
548+
}
549+
for _, opt := range acc.ProductOptions {
550+
if opt.Name == option {
551+
return &opt, nil
552+
}
553+
}
554+
}
555+
556+
return nil, fmt.Errorf("Specified CA product option not found.")
557+
}

0 commit comments

Comments
 (0)