Skip to content

Commit 29ab080

Browse files
committed
feat: add Omni edge location data source
1 parent 7a9426b commit 29ab080

File tree

4 files changed

+252
-1
lines changed

4 files changed

+252
-1
lines changed

castai/data_source_omni_cluster.go

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package castai
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
8+
"github.com/hashicorp/terraform-plugin-framework/datasource"
9+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
10+
"github.com/hashicorp/terraform-plugin-framework/types"
11+
)
12+
13+
var (
14+
_ datasource.DataSource = (*omniClusterDataSource)(nil)
15+
_ datasource.DataSourceWithConfigure = (*omniClusterDataSource)(nil)
16+
)
17+
18+
type omniClusterDataSource struct {
19+
client *ProviderConfig
20+
}
21+
22+
type omniClusterDataSourceModel struct {
23+
ID types.String `tfsdk:"id"`
24+
OrganizationID types.String `tfsdk:"organization_id"`
25+
ClusterID types.String `tfsdk:"cluster_id"`
26+
Name types.String `tfsdk:"name"`
27+
State types.String `tfsdk:"state"`
28+
ProviderType types.String `tfsdk:"provider_type"`
29+
ServiceAccountID types.String `tfsdk:"service_account_id"`
30+
CastaiOidcConfig *castaiOidcConfigModel `tfsdk:"castai_oidc_config"`
31+
}
32+
33+
type castaiOidcConfigModel struct {
34+
GcpServiceAccountEmail types.String `tfsdk:"gcp_service_account_email"`
35+
GcpServiceAccountUniqueID types.String `tfsdk:"gcp_service_account_unique_id"`
36+
}
37+
38+
func newOmniClusterDataSource() datasource.DataSource {
39+
return &omniClusterDataSource{}
40+
}
41+
42+
func (d *omniClusterDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
43+
resp.TypeName = req.ProviderTypeName + "_omni_cluster"
44+
}
45+
46+
func (d *omniClusterDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
47+
resp.Schema = schema.Schema{
48+
Description: "Retrieve information about a CAST AI Omni cluster",
49+
Attributes: map[string]schema.Attribute{
50+
"id": schema.StringAttribute{
51+
Computed: true,
52+
Description: "Cluster ID (same as cluster_id)",
53+
},
54+
"organization_id": schema.StringAttribute{
55+
Required: true,
56+
Description: "CAST AI organization ID",
57+
},
58+
"cluster_id": schema.StringAttribute{
59+
Required: true,
60+
Description: "CAST AI cluster ID",
61+
},
62+
"name": schema.StringAttribute{
63+
Computed: true,
64+
Description: "Name of the cluster",
65+
},
66+
"state": schema.StringAttribute{
67+
Computed: true,
68+
Description: "State of the cluster on API level",
69+
},
70+
"provider_type": schema.StringAttribute{
71+
Computed: true,
72+
Description: "Provider type of the cluster (e.g. GKE, EKS)",
73+
},
74+
"service_account_id": schema.StringAttribute{
75+
Computed: true,
76+
Description: "CAST AI service account ID associated with OMNI operations",
77+
},
78+
"castai_oidc_config": schema.SingleNestedAttribute{
79+
Computed: true,
80+
Description: "CAST AI OIDC configuration for service account impersonation",
81+
Attributes: map[string]schema.Attribute{
82+
"gcp_service_account_email": schema.StringAttribute{
83+
Computed: true,
84+
Description: "CAST AI GCP service account email for impersonation",
85+
},
86+
"gcp_service_account_unique_id": schema.StringAttribute{
87+
Computed: true,
88+
Description: "CAST AI GCP service account unique ID for impersonation",
89+
},
90+
},
91+
},
92+
},
93+
}
94+
}
95+
96+
func (d *omniClusterDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
97+
if req.ProviderData == nil {
98+
return
99+
}
100+
101+
client, ok := req.ProviderData.(*ProviderConfig)
102+
if !ok {
103+
resp.Diagnostics.AddError(
104+
"Unexpected Data Source Configure Type",
105+
fmt.Sprintf("Expected *ProviderConfig, got: %T", req.ProviderData),
106+
)
107+
return
108+
}
109+
110+
d.client = client
111+
}
112+
113+
func (d *omniClusterDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
114+
var data omniClusterDataSourceModel
115+
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
116+
if resp.Diagnostics.HasError() {
117+
return
118+
}
119+
120+
client := d.client.omniAPI
121+
organizationID := data.OrganizationID.ValueString()
122+
clusterID := data.ClusterID.ValueString()
123+
124+
apiResp, err := client.ClustersAPIGetClusterWithResponse(ctx, organizationID, clusterID, nil)
125+
if err != nil {
126+
resp.Diagnostics.AddError("Failed to read omni cluster", err.Error())
127+
return
128+
}
129+
130+
if apiResp.StatusCode() != http.StatusOK {
131+
resp.Diagnostics.AddError(
132+
"Failed to read omni cluster",
133+
fmt.Sprintf("unexpected status code: %d, body: %s", apiResp.StatusCode(), string(apiResp.Body)),
134+
)
135+
return
136+
}
137+
138+
cluster := apiResp.JSON200
139+
140+
data.ID = types.StringValue(clusterID)
141+
data.Name = types.StringPointerValue(cluster.Name)
142+
data.ServiceAccountID = types.StringPointerValue(cluster.ServiceAccountId)
143+
144+
if cluster.State != nil {
145+
data.State = types.StringValue(string(*cluster.State))
146+
}
147+
if cluster.ProviderType != nil {
148+
data.ProviderType = types.StringValue(string(*cluster.ProviderType))
149+
}
150+
151+
if cluster.CastaiOidcConfig != nil {
152+
data.CastaiOidcConfig = &castaiOidcConfigModel{
153+
GcpServiceAccountEmail: types.StringPointerValue(cluster.CastaiOidcConfig.GcpServiceAccountEmail),
154+
GcpServiceAccountUniqueID: types.StringPointerValue(cluster.CastaiOidcConfig.GcpServiceAccountUniqueId),
155+
}
156+
}
157+
158+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
159+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package castai
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
9+
)
10+
11+
func TestAccCloudAgnostic_DataSourceOmniCluster(t *testing.T) {
12+
clusterName := "omni-tf-acc-gcp"
13+
dataSourceName := "data.castai_omni_cluster.test"
14+
resourceName := "castai_omni_cluster.test"
15+
16+
resource.Test(t, resource.TestCase{
17+
PreCheck: func() { testAccPreCheck(t) },
18+
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
19+
Steps: []resource.TestStep{
20+
{
21+
Config: testAccOmniClusterDataSourceConfig(clusterName),
22+
Check: resource.ComposeTestCheckFunc(
23+
// Verify data source ID matches the resource ID
24+
resource.TestCheckResourceAttrPair(dataSourceName, "id", resourceName, "id"),
25+
// Verify organization_id is correctly passed through
26+
resource.TestCheckResourceAttr(dataSourceName, "organization_id", testAccGetOrganizationID()),
27+
// Verify cluster metadata fields are populated
28+
resource.TestCheckResourceAttrSet(dataSourceName, "name"),
29+
resource.TestCheckResourceAttrSet(dataSourceName, "state"),
30+
// Verify OIDC config fields have expected formats
31+
resource.TestMatchResourceAttr(dataSourceName, "castai_oidc_config.gcp_service_account_email",
32+
regexp.MustCompile(`^.+@.+\.iam\.gserviceaccount\.com$`)),
33+
resource.TestMatchResourceAttr(dataSourceName, "castai_oidc_config.gcp_service_account_unique_id",
34+
regexp.MustCompile(`^\d+$`)),
35+
),
36+
},
37+
},
38+
})
39+
}
40+
41+
func testAccOmniClusterDataSourceConfig(clusterName string) string {
42+
organizationID := testAccGetOrganizationID()
43+
44+
return ConfigCompose(testOmniClusterConfig(clusterName), fmt.Sprintf(`
45+
data "castai_omni_cluster" "test" {
46+
organization_id = %[1]q
47+
cluster_id = castai_omni_cluster.test.id
48+
}
49+
`, organizationID))
50+
}

castai/provider_framework.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,7 @@ func (p *frameworkProvider) Resources(_ context.Context) []func() resource.Resou
132132
}
133133

134134
func (p *frameworkProvider) DataSources(_ context.Context) []func() datasource.DataSource {
135-
return []func() datasource.DataSource{}
135+
return []func() datasource.DataSource{
136+
newOmniClusterDataSource,
137+
}
136138
}

docs/data-sources/omni_cluster.md

Lines changed: 40 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)