Skip to content

Commit ec6b31e

Browse files
authored
Merge pull request #9 from SiM22/feature/rdp-client-connection-info
Feature: Implement RDP client connection info data source with acceptance tests
2 parents 8eb3376 + 99e4b0c commit ec6b31e

File tree

8 files changed

+678
-26
lines changed

8 files changed

+678
-26
lines changed

docs/API_IMPLEMENTATION_STATUS.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ These APIs are officially documented in the Kasm API documentation.
9191
#### RDP Client Connection
9292
| API Endpoint | Implementation Status | Resource Name | File Location | Tests | Test File |
9393
|--------------|---------------------|---------------|---------------|-------|-----------|
94-
| POST /api/public/get_rdp_client_connection_info | Not Implemented | - | - | | - |
94+
| POST /api/public/get_rdp_client_connection_info | Implemented | kasm_rdp_client_connection_info | internal/datasources/rdp | | internal/datasources/rdp/tests/datasource_test.go |
9595

9696
#### Egress Management
9797
| API Endpoint | Implementation Status | Resource Name | File Location | Tests | Test File |
@@ -168,6 +168,11 @@ These APIs are officially documented in the Kasm API documentation.
168168
| DELETE /api/public/delete_group_membership | Implemented | kasm_group_membership | internal/resources/group_membership || internal/resources/group_membership/tests/group_membership_test.go |
169169
| POST /api/public/get_group_memberships | Implemented | kasm_group_memberships | internal/datasources/group_memberships || internal/resources/group_membership/tests/group_membership_test.go |
170170

171+
#### RDP Client Connection
172+
| API Endpoint | Implementation Status | Data Source Name | File Location | Tests | Test File |
173+
|--------------|---------------------|------------------|---------------|-------|-----------|
174+
| POST /api/public/get_rdp_client_connection_info | Implemented | kasm_rdp_client_connection_info | internal/datasources/rdp || internal/datasources/rdp/tests/datasource_test.go |
175+
171176
## Undocumented APIs
172177

173178
These APIs are not officially documented in the Kasm API documentation but are used by the Kasm web UI.
@@ -205,7 +210,6 @@ These APIs are not officially documented in the Kasm API documentation but are u
205210
1. Session Features:
206211
- POST /api/public/screenshot (for kasm_screenshot) - Client implementation exists
207212
- POST /api/public/exec_command (for kasm_exec) - Client implementation exists
208-
- POST /api/public/get_rdp_client_connection_info (for kasm_rdp) - Client implementation exists
209213

210214
### Additional Undocumented Resources Found
211215
1. Login Management:
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# RDP Client Connection Info Data Source
2+
3+
Retrieves RDP client connection information for a Kasm session.
4+
5+
> **Note:** This functionality requires a Windows RDP server configured in Kasm. For container-based sessions, the RDP connection info will be empty. See the [Kasm documentation on Fixed Infrastructure](https://kasmweb.com/docs/latest/how_to/fixed_infrastructure.html#fixed-infrastructure-rdp-vnc-ssh-kasmvnc) for more details on setting up RDP servers.
6+
7+
## Example Usage
8+
9+
### Basic Usage
10+
```hcl
11+
data "kasm_rdp_client_connection_info" "example_file" {
12+
user_id = "44edb3e5-2909-4927-a60b-6e09c7219104"
13+
kasm_id = "898813d7-a677-4c60-8999-c9ea346a3e21"
14+
connection_type = "file"
15+
}
16+
17+
output "rdp_file" {
18+
value = data.kasm_rdp_client_connection_info.example_file.file
19+
}
20+
21+
data "kasm_rdp_client_connection_info" "example_url" {
22+
user_id = "44edb3e5-2909-4927-a60b-6e09c7219104"
23+
kasm_id = "898813d7-a677-4c60-8999-c9ea346a3e21"
24+
connection_type = "url"
25+
}
26+
27+
output "rdp_url" {
28+
value = data.kasm_rdp_client_connection_info.example_url.url
29+
}
30+
```
31+
32+
### Advanced Usage
33+
```hcl
34+
data "kasm_rdp_client_connection_info" "custom" {
35+
user_id = kasm_user.example.id
36+
kasm_id = kasm_session.example.id
37+
connection_type = "file"
38+
}
39+
40+
output "rdp_file" {
41+
value = data.kasm_rdp_client_connection_info.custom.file
42+
sensitive = true
43+
}
44+
```
45+
46+
## Argument Reference
47+
48+
* `user_id` - (Required) The ID of the user requesting the connection.
49+
* `kasm_id` - (Required) The ID of the Kasm session.
50+
* `connection_type` - (Optional) The type of connection to retrieve ("url" or "file"). Defaults to "url".
51+
52+
## Attribute Reference
53+
54+
* `id` - The unique identifier for the connection info.
55+
* `file` - The RDP connection file content (if connection_type is "file").
56+
* `url` - The URL for RDP access (if connection_type is "url").
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package rdp
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/datasource"
8+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
9+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
10+
"github.com/hashicorp/terraform-plugin-framework/types"
11+
"github.com/hashicorp/terraform-plugin-log/tflog"
12+
13+
"terraform-provider-kasm/internal/client"
14+
"terraform-provider-kasm/internal/validators"
15+
)
16+
17+
// Ensure the implementation satisfies the expected interfaces.
18+
var (
19+
_ datasource.DataSource = &rdpClientConnectionInfoDataSource{}
20+
)
21+
22+
// NewRDPClientConnectionInfoDataSource is a helper function to simplify the provider implementation.
23+
func NewRDPClientConnectionInfoDataSource() datasource.DataSource {
24+
return &rdpClientConnectionInfoDataSource{
25+
client: &client.Client{},
26+
}
27+
}
28+
29+
// rdpClientConnectionInfoDataSource is the data source implementation.
30+
type rdpClientConnectionInfoDataSource struct {
31+
client *client.Client
32+
}
33+
34+
// Metadata returns the data source type name.
35+
func (d *rdpClientConnectionInfoDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
36+
resp.TypeName = req.ProviderTypeName + "_rdp_client_connection_info"
37+
}
38+
39+
// Schema defines the schema for the data source.
40+
func (d *rdpClientConnectionInfoDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
41+
resp.Schema = schema.Schema{
42+
Description: "Retrieves RDP client connection information for a Kasm session.",
43+
Attributes: map[string]schema.Attribute{
44+
"id": schema.StringAttribute{
45+
Computed: true,
46+
Description: "Identifier of the RDP client connection info.",
47+
},
48+
"user_id": schema.StringAttribute{
49+
Required: true,
50+
Description: "The ID of the user for which to retrieve the RDP connection info.",
51+
},
52+
"kasm_id": schema.StringAttribute{
53+
Required: true,
54+
Description: "The ID of the Kasm session for which to retrieve the RDP connection info.",
55+
},
56+
"connection_type": schema.StringAttribute{
57+
Optional: true,
58+
Description: "Type of connection to retrieve (url or file)",
59+
Validators: []validator.String{
60+
validators.StringOneOf("url", "file"),
61+
},
62+
},
63+
"file": schema.StringAttribute{
64+
Computed: true,
65+
Description: "The RDP file content (if connection_type is 'file' or not specified).",
66+
},
67+
"url": schema.StringAttribute{
68+
Computed: true,
69+
Description: "The RDP URL (if connection_type is 'url').",
70+
},
71+
},
72+
}
73+
}
74+
75+
// Configure adds the provider configured client to the data source.
76+
func (d *rdpClientConnectionInfoDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
77+
if req.ProviderData == nil {
78+
return
79+
}
80+
81+
client, ok := req.ProviderData.(*client.Client)
82+
if !ok {
83+
resp.Diagnostics.AddError(
84+
"Unexpected Data Source Configure Type",
85+
fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
86+
)
87+
return
88+
}
89+
90+
d.client = client
91+
}
92+
93+
// Read refreshes the Terraform state with the latest data.
94+
func (d *rdpClientConnectionInfoDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
95+
var state rdpClientConnectionInfoModel
96+
97+
// Read Terraform configuration data into the model
98+
resp.Diagnostics.Append(req.Config.Get(ctx, &state)...)
99+
if resp.Diagnostics.HasError() {
100+
return
101+
}
102+
103+
// Get the connection info from the API
104+
connectionType := client.RDPConnectionTypeFile
105+
if !state.ConnectionType.IsNull() && state.ConnectionType.ValueString() == "url" {
106+
connectionType = client.RDPConnectionTypeURL
107+
}
108+
109+
tflog.Debug(ctx, fmt.Sprintf("Getting RDP connection info for user %s, kasm %s, type %s", state.UserID.ValueString(), state.KasmID.ValueString(), connectionType))
110+
connectionInfo, err := d.client.GetRDPConnectionInfo(state.UserID.ValueString(), state.KasmID.ValueString(), connectionType)
111+
if err != nil {
112+
resp.Diagnostics.AddError(
113+
"Error getting RDP connection info",
114+
fmt.Sprintf("Could not get RDP connection info: %v", err),
115+
)
116+
return
117+
}
118+
119+
// Set the ID
120+
state.ID = types.StringValue(fmt.Sprintf("%s-%s-%s", state.UserID.ValueString(), state.KasmID.ValueString(), connectionType))
121+
122+
// Set the connection info
123+
state.File = types.StringValue(connectionInfo.File)
124+
state.URL = types.StringValue(connectionInfo.URL)
125+
126+
// Save the data into Terraform state
127+
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
128+
}
129+
130+
// rdpClientConnectionInfoModel maps the data source schema data.
131+
type rdpClientConnectionInfoModel struct {
132+
ID types.String `tfsdk:"id"`
133+
UserID types.String `tfsdk:"user_id"`
134+
KasmID types.String `tfsdk:"kasm_id"`
135+
ConnectionType types.String `tfsdk:"connection_type"`
136+
File types.String `tfsdk:"file"`
137+
URL types.String `tfsdk:"url"`
138+
}

0 commit comments

Comments
 (0)