package provider import ( "context" "fmt" "github.com/DevFW-CICD/terraform-provider-edge-connect/internal/client" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" ) // Ensure the implementation satisfies the expected interfaces. var ( _ datasource.DataSource = &appDataSource{} _ datasource.DataSourceWithConfigure = &appDataSource{} ) // NewAppDataSource is a helper function to simplify the provider implementation. func NewAppDataSource() datasource.DataSource { return &appDataSource{} } // appDataSource is the data source implementation. type appDataSource struct { client *client.Client } // appDataSourceModel maps the data source schema data. type appDataSourceModel struct { ID types.String `tfsdk:"id"` Region types.String `tfsdk:"region"` Organization types.String `tfsdk:"organization"` Name types.String `tfsdk:"name"` Version types.String `tfsdk:"version"` ImageType types.String `tfsdk:"image_type"` ImagePath types.String `tfsdk:"image_path"` DefaultFlavor types.String `tfsdk:"default_flavor"` Deployment types.String `tfsdk:"deployment"` DeploymentManifest types.String `tfsdk:"deployment_manifest"` AccessPorts types.String `tfsdk:"access_ports"` Annotations types.String `tfsdk:"annotations"` CreatedAt types.String `tfsdk:"created_at"` UpdatedAt types.String `tfsdk:"updated_at"` } // Metadata returns the data source type name. func (d *appDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_app" } // Schema defines the schema for the data source. func (d *appDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ Description: "Fetches an Edge Connect application specification.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ Description: "The unique identifier for the app (format: region/organization/name/version).", Computed: true, }, "region": schema.StringAttribute{ Description: "The region where the app is deployed (e.g., 'EU').", Required: true, }, "organization": schema.StringAttribute{ Description: "The organization that owns the app.", Required: true, }, "name": schema.StringAttribute{ Description: "The name of the application.", Required: true, }, "version": schema.StringAttribute{ Description: "The version of the application.", Required: true, }, "image_type": schema.StringAttribute{ Description: "The type of image (e.g., 'Docker').", Computed: true, }, "image_path": schema.StringAttribute{ Description: "The path to the container image.", Computed: true, }, "default_flavor": schema.StringAttribute{ Description: "The default flavor for the app.", Computed: true, }, "deployment": schema.StringAttribute{ Description: "The deployment type (e.g., 'kubernetes').", Computed: true, }, "deployment_manifest": schema.StringAttribute{ Description: "The Kubernetes deployment manifest (YAML).", Computed: true, }, "access_ports": schema.StringAttribute{ Description: "The access ports in format 'protocol:port'.", Computed: true, }, "annotations": schema.StringAttribute{ Description: "Annotations for the app.", Computed: true, }, "created_at": schema.StringAttribute{ Description: "The timestamp when the app was created.", Computed: true, }, "updated_at": schema.StringAttribute{ Description: "The timestamp when the app was last updated.", Computed: true, }, }, } } // Configure adds the provider configured client to the data source. func (d *appDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { if req.ProviderData == nil { return } client, ok := req.ProviderData.(*client.Client) if !ok { resp.Diagnostics.AddError( "Unexpected Data Source Configure Type", fmt.Sprintf("Expected *client.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), ) return } d.client = client } // Read refreshes the Terraform state with the latest data. func (d *appDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { var config appDataSourceModel diags := req.Config.Get(ctx, &config) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } // Get app from API app := client.App{} app.Key.Organization = config.Organization.ValueString() app.Key.Name = config.Name.ValueString() app.Key.Version = config.Version.ValueString() readApp, err := d.client.GetApp(config.Region.ValueString(), app) if err != nil { resp.Diagnostics.AddError( "Error reading app", "Could not read app: "+err.Error(), ) return } // Map response to data source model config.ID = types.StringValue(fmt.Sprintf("%s/%s/%s/%s", config.Region.ValueString(), readApp.Key.Organization, readApp.Key.Name, readApp.Key.Version)) config.ImageType = types.StringValue(readApp.ImageType) config.ImagePath = types.StringValue(readApp.ImagePath) config.DefaultFlavor = types.StringValue(readApp.DefaultFlavor) config.Deployment = types.StringValue(readApp.Deployment) config.DeploymentManifest = types.StringValue(readApp.DeploymentManifest) config.AccessPorts = types.StringValue(readApp.AccessPorts) config.Annotations = types.StringValue(readApp.Annotations) config.CreatedAt = types.StringValue(readApp.CreatedAt) config.UpdatedAt = types.StringValue(readApp.UpdatedAt) diags = resp.State.Set(ctx, &config) resp.Diagnostics.Append(diags...) }