diff --git a/docs/data-sources/profile.md b/docs/data-sources/profile.md index 871edc3..53209ef 100644 --- a/docs/data-sources/profile.md +++ b/docs/data-sources/profile.md @@ -22,22 +22,22 @@ resource "incus_instance" "d1" { * `project` - *Optional* - Name of the project where the profile will be stored. -* `remote` - *Optional* - The remote in which the resource will be created. If +* `remote` - *Optional* - The remote in which the resource was created. If not provided, the provider's default remote will be used. ## Attribute Reference -* `device` - *Optional* - Device definition. See reference below. +* `device` - Device definition. See reference below. -* `config` - *Optional* - Map of key/value pairs of +* `config` - Map of key/value pairs of [instance config settings](https://linuxcontainers.org/incus/docs/main/reference/instance_options/). The `device` block supports: -* `name` - **Required** - Name of the device. +* `name` - Name of the device. -* `type` - **Required** - Type of the device Must be one of none, disk, nic, +* `type` - Type of the device Must be one of none, disk, nic, unix-char, unix-block, usb, gpu, infiniband, proxy, unix-hotplug, tpm, pci. -* `properties`- **Required** - Map of key/value pairs of +* `properties` - Map of key/value pairs of [device properties](https://linuxcontainers.org/incus/docs/main/reference/devices/). diff --git a/docs/data-sources/project.md b/docs/data-sources/project.md new file mode 100644 index 0000000..4937ddc --- /dev/null +++ b/docs/data-sources/project.md @@ -0,0 +1,32 @@ +# incus_project + +Provides information about an Incus project. + +## Example Usage + +```hcl +data "incus_project" "default" { + name = "default" +} + +resource "incus_instance" "d1" { + project = data.incus_project.default.name + image = "images:debian/12" + name = "d1" +} +``` + +## Argument Reference + +* `name` - **Required** - Name of the project. + +* `remote` - *Optional* - The remote in which the resource was created. If + not provided, the provider's default remote will be used. + +## Attribute Reference + +* `description` - Description of the project. + +* `config` - Map of key/value pairs of + [instance config settings](https://linuxcontainers.org/incus/docs/main/reference/instance_options/). + diff --git a/internal/project/datasource_project.go b/internal/project/datasource_project.go new file mode 100644 index 0000000..d7a6ab5 --- /dev/null +++ b/internal/project/datasource_project.go @@ -0,0 +1,96 @@ +package project + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + + "github.com/lxc/terraform-provider-incus/internal/common" + "github.com/lxc/terraform-provider-incus/internal/errors" + provider_config "github.com/lxc/terraform-provider-incus/internal/provider-config" +) + +type ProjectDataSource struct { + provider *provider_config.IncusProviderConfig +} + +func NewProjectDataSource() datasource.DataSource { + return &ProjectDataSource{} +} + +func (d *ProjectDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = fmt.Sprintf("%s_project", req.ProviderTypeName) +} + +func (d *ProjectDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "name": schema.StringAttribute{ + Required: true, + }, + "description": schema.StringAttribute{ + Optional: true, + Computed: true, + }, + "config": schema.MapAttribute{ + Optional: true, + Computed: true, + ElementType: types.StringType, + }, + "remote": schema.StringAttribute{ + Optional: true, + }, + }, + } +} + +func (d *ProjectDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + data := req.ProviderData + if data == nil { + return + } + + provider, ok := data.(*provider_config.IncusProviderConfig) + if !ok { + resp.Diagnostics.Append(errors.NewProviderDataTypeError(req.ProviderData)) + return + } + + d.provider = provider +} + +func (d *ProjectDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var state ProjectModel + + diags := req.Config.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + remote := state.Remote.ValueString() + projectName := state.Name.ValueString() + server, err := d.provider.InstanceServer(remote, projectName, "") + if err != nil { + resp.Diagnostics.Append(errors.NewInstanceServerError(err)) + return + } + + project, _, err := server.GetProject(projectName) + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("Failed to retrieve existing project %q", projectName), err.Error()) + return + } + + config, diags := common.ToConfigMapType(ctx, common.ToNullableConfig(project.Config), state.Config) + + state.Name = types.StringValue(project.Name) + state.Description = types.StringValue(project.Description) + state.Config = config + + diags = resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 4476ce9..d58cd18 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -284,5 +284,6 @@ func (p *IncusProvider) DataSources(_ context.Context) []func() datasource.DataS return []func() datasource.DataSource{ image.NewImageDataSource, profile.NewProfileDataSource, + project.NewProjectDataSource, } }