From 9774165728ef03fbe90537236d191b515af2de80 Mon Sep 17 00:00:00 2001 From: Juha Ylitalo Date: Sat, 1 Mar 2025 23:39:34 +0200 Subject: [PATCH] feature - Add tableau_workbook_connections as data source (#43) * Adds tableau_workbook_connections as data source * Update tableau/workbook_connections_data_source.go Co-authored-by: Gary James <13685708+GtheSheep@users.noreply.github.com> * Update tableau/workbook_connections_data_source.go Co-authored-by: Gary James <13685708+GtheSheep@users.noreply.github.com> * Update tableau/workbook_connections_data_source.go Co-authored-by: Gary James <13685708+GtheSheep@users.noreply.github.com> * Update tableau/workbook_connections_data_source.go Co-authored-by: Gary James <13685708+GtheSheep@users.noreply.github.com> --------- Co-authored-by: Gary James <13685708+GtheSheep@users.noreply.github.com> --- docs/data-sources/workbook_connections.md | 46 ++++++ .../data-source.tf | 3 + tableau/provider.go | 1 + tableau/workbook_connection.go | 59 +++++++ tableau/workbook_connections_data_source.go | 148 ++++++++++++++++++ 5 files changed, 257 insertions(+) create mode 100644 docs/data-sources/workbook_connections.md create mode 100644 examples/data-sources/tableau_workbook_connections/data-source.tf create mode 100644 tableau/workbook_connection.go create mode 100644 tableau/workbook_connections_data_source.go diff --git a/docs/data-sources/workbook_connections.md b/docs/data-sources/workbook_connections.md new file mode 100644 index 0000000..83cf732 --- /dev/null +++ b/docs/data-sources/workbook_connections.md @@ -0,0 +1,46 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "tableau_workbook_connections Data Source - terraform-provider-tableau" +subcategory: "" +description: |- + Retrieve virtual connection connections details +--- + +# tableau_workbook_connections (Data Source) + +Retrieve virtual connection connections details + +## Example Usage + +```terraform +data "tableau_workbook_connections" "example" { + id = data.tableau_workbooks.wb[0].id +} +``` + + +## Schema + +### Required + +- `id` (String) ID of the virtual connections + +### Read-Only + +- `connections` (Attributes List) List database connections of virtual connection and their attributes (see [below for nested schema](#nestedatt--connections)) + + +### Nested Schema for `connections` + +Read-Only: + +- `authentication_type` (String) Authentication type +- `datasource_id` (String) ID of datasource +- `embed_password` (Boolean) Embed database password into connection +- `id` (String) ID of the connection in Virtual Connection +- `query_tagging_enabled` (Boolean) Query tagging enabled +- `server_address` (String) Server address +- `server_port` (String) Server port +- `type` (String) Database connection type +- `use_oauth_managed_keychain` (Boolean) Use OAuth managed keychain +- `username` (String) Username diff --git a/examples/data-sources/tableau_workbook_connections/data-source.tf b/examples/data-sources/tableau_workbook_connections/data-source.tf new file mode 100644 index 0000000..de28ca9 --- /dev/null +++ b/examples/data-sources/tableau_workbook_connections/data-source.tf @@ -0,0 +1,3 @@ +data "tableau_workbook_connections" "example" { + id = data.tableau_workbooks.wb[0].id +} diff --git a/tableau/provider.go b/tableau/provider.go index 463c62b..13e24e6 100644 --- a/tableau/provider.go +++ b/tableau/provider.go @@ -260,6 +260,7 @@ func (p *tableauProvider) DataSources(_ context.Context) []func() datasource.Dat VirtualConnectionsDataSource, VirtualConnectionConnectionsDataSource, VirtualConnectionRevisionsDataSource, + WorkbookConnectionsDataSource, WorkbooksDataSource, WorkbookRevisionsDataSource, } diff --git a/tableau/workbook_connection.go b/tableau/workbook_connection.go new file mode 100644 index 0000000..309b2fd --- /dev/null +++ b/tableau/workbook_connection.go @@ -0,0 +1,59 @@ +package tableau + +import ( + "encoding/json" + "fmt" + "net/http" +) + +type WorkbookConnection struct { + WorkbookID string + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + ServerAddress string `json:"serverAddress,omitempty"` + ServerPort string `json:"serverPort,omitempty"` + UserName string `json:"userName,omitempty"` + QueryTaggingEnabled bool `json:"query_tagging_enabled,omitempty"` + AuthenticationType string `json:"authenticationType,omitempty"` + EmbedPassword bool `json:"embedPassword,omitempty"` + UseOAuthManagedKeychain bool `json:"useOauthManagedKeychain,omitempty"` + DataSourceID struct { + ID string `json:"id,omitempty"` + // Name string `json:"name,omitempty"` + } `json:"datasource,omitempty"` +} + +type WorkbookConnectionRequest struct { + WorkbookConnection WorkbookConnection `json:"workbookConnections"` +} + +type WorkbookConnectionsResponse struct { + WorkbookConnections []WorkbookConnection `json:"connection"` +} + +type WorkbookConnectionListResponse struct { + WorkbookConnectionsResponse WorkbookConnectionsResponse `json:"connections"` +} + +func (c *Client) GetWorkbookConnections(workbookID string) ([]WorkbookConnection, error) { + req, err := http.NewRequest("GET", fmt.Sprintf("%s/workbooks/%s/connections", c.ApiUrl, workbookID), nil) + if err != nil { + return nil, err + } + + body, err := c.doRequest(req) + if err != nil { + return nil, err + } + workbookConnectionsListResponse := WorkbookConnectionListResponse{} + err = json.Unmarshal(body, &workbookConnectionsListResponse) + if err != nil { + return nil, err + } + // workbook connections don't seem to have pagination + allWorkbookConnections := workbookConnectionsListResponse.WorkbookConnectionsResponse.WorkbookConnections + for idx := range allWorkbookConnections { + allWorkbookConnections[idx].WorkbookID = workbookID + } + return allWorkbookConnections, nil +} diff --git a/tableau/workbook_connections_data_source.go b/tableau/workbook_connections_data_source.go new file mode 100644 index 0000000..c759347 --- /dev/null +++ b/tableau/workbook_connections_data_source.go @@ -0,0 +1,148 @@ +package tableau + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +var ( + _ datasource.DataSource = &workbookConnectionsDataSource{} + _ datasource.DataSourceWithConfigure = &workbookConnectionsDataSource{} +) + +func WorkbookConnectionsDataSource() datasource.DataSource { + return &workbookConnectionsDataSource{} +} + +type workbookConnectionsDataSource struct { + client *Client +} + +type workbookConnectionNestedDataModel struct { + ID types.String `tfsdk:"id"` + Type types.String `tfsdk:"type"` + DatasourceID types.String `tfsdk:"datasource_id"` + ServerAddress types.String `tfsdk:"server_address"` + ServerPort types.String `tfsdk:"server_port"` + UserName types.String `tfsdk:"username"` + EmbedPassword types.Bool `tfsdk:"embed_password"` + QueryTaggingEnabled types.Bool `tfsdk:"query_tagging_enabled"` + AuthenticationType types.String `tfsdk:"authentication_type"` + UseOAuthManagedKeychain types.Bool `tfsdk:"use_oauth_managed_keychain"` +} + +type workbookConnectionsDataSourceModel struct { + ID types.String `tfsdk:"id"` + Connections []workbookConnectionNestedDataModel `tfsdk:"connections"` +} + +func (d *workbookConnectionsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_workbook_connections" +} + +func (d *workbookConnectionsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Retrieve workbook connections details", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Required: true, + Description: "ID of the workbook", + }, + "connections": schema.ListNestedAttribute{ + Description: "List workbook connections and their attributes", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + Description: "ID of the workbook connection", + }, + "type": schema.StringAttribute{ + Computed: true, + Description: "Database connection type", + }, + "datasource_id": schema.StringAttribute{ + Computed: true, + Description: "ID of datasource", + }, + "server_address": schema.StringAttribute{ + Computed: true, + Description: "Server address", + }, + "server_port": schema.StringAttribute{ + Computed: true, + Description: "Server port", + }, + "username": schema.StringAttribute{ + Computed: true, + Description: "Username", + }, + "embed_password": schema.BoolAttribute{ + Computed: true, + Description: "Embed database password into connection", + }, + "query_tagging_enabled": schema.BoolAttribute{ + Computed: true, + Description: "Query tagging enabled", + }, + "authentication_type": schema.StringAttribute{ + Computed: true, + Description: "Authentication type", + }, + "use_oauth_managed_keychain": schema.BoolAttribute{ + Computed: true, + Description: "Use OAuth managed keychain", + }, + }, + }, + }, + }, + } +} + +func (d *workbookConnectionsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var state workbookConnectionsDataSourceModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &state)...) + + connections, err := d.client.GetWorkbookConnections(state.ID.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "Unable to Read Tableau Workbook Connections", + err.Error(), + ) + return + } + for _, connection := range connections { + workbookConnection := workbookConnectionNestedDataModel{ + ID: types.StringValue(connection.ID), + Type: types.StringValue(connection.Type), + DatasourceID: types.StringValue(connection.DataSourceID.ID), + ServerAddress: types.StringValue(connection.ServerAddress), + ServerPort: types.StringValue(connection.ServerPort), + UserName: types.StringValue(connection.UserName), + EmbedPassword: types.BoolValue(connection.EmbedPassword), + QueryTaggingEnabled: types.BoolValue(connection.QueryTaggingEnabled), + AuthenticationType: types.StringValue(connection.AuthenticationType), + UseOAuthManagedKeychain: types.BoolValue(connection.UseOAuthManagedKeychain), + } + state.Connections = append(state.Connections, workbookConnection) + } + + diags := resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +func (d *workbookConnectionsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, _ *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + d.client = req.ProviderData.(*Client) +}