mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-06-29 18:21:10 +00:00
feat(datastores)!: implement new structured format and filters for datastores
data source (#1875)
Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
parent
ece13f7716
commit
b5b61b48dc
@ -3,32 +3,54 @@ layout: page
|
|||||||
title: proxmox_virtual_environment_datastores
|
title: proxmox_virtual_environment_datastores
|
||||||
parent: Data Sources
|
parent: Data Sources
|
||||||
subcategory: Virtual Environment
|
subcategory: Virtual Environment
|
||||||
|
description: |-
|
||||||
|
Retrieves information about all the datastores available to a specific node.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Data Source: proxmox_virtual_environment_datastores
|
# Data Source: proxmox_virtual_environment_datastores
|
||||||
|
|
||||||
Retrieves information about all the datastores available to a specific node.
|
Retrieves information about all the datastores available to a specific node.
|
||||||
|
|
||||||
## Example Usage
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
data "proxmox_virtual_environment_datastores" "first_node" {
|
|
||||||
node_name = "first-node"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Argument Reference
|
<!-- schema generated by tfplugindocs -->
|
||||||
|
## Schema
|
||||||
|
|
||||||
- `node_name` - (Required) A node name.
|
### Required
|
||||||
|
|
||||||
## Attribute Reference
|
- `node_name` (String) The name of the node to retrieve the stores from.
|
||||||
|
|
||||||
- `active` - Whether the datastore is active.
|
### Optional
|
||||||
- `content_types` - The allowed content types.
|
|
||||||
- `datastore_ids` - The datastore identifiers.
|
- `datastores` (Attributes List) The list of datastores. (see [below for nested schema](#nestedatt--datastores))
|
||||||
- `enabled` - Whether the datastore is enabled.
|
- `filters` (Attributes) The filters to apply to the stores. (see [below for nested schema](#nestedatt--filters))
|
||||||
- `shared` - Whether the datastore is shared.
|
|
||||||
- `space_available` - The available space in bytes.
|
<a id="nestedatt--datastores"></a>
|
||||||
- `space_total` - The total space in bytes.
|
### Nested Schema for `datastores`
|
||||||
- `space_used` - The used space in bytes.
|
|
||||||
- `types` - The storage types.
|
Required:
|
||||||
|
|
||||||
|
- `content_types` (Set of String) Allowed store content types.
|
||||||
|
- `id` (String) The ID of the store.
|
||||||
|
- `node_name` (String) The name of the node the store is on.
|
||||||
|
- `type` (String) Store type.
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
|
||||||
|
- `active` (Boolean) Whether the store is active.
|
||||||
|
- `enabled` (Boolean) Whether the store is enabled.
|
||||||
|
- `shared` (Boolean) Shared flag from store configuration.
|
||||||
|
- `space_available` (Number) Available store space in bytes.
|
||||||
|
- `space_total` (Number) Total store space in bytes.
|
||||||
|
- `space_used` (Number) Used store space in bytes.
|
||||||
|
- `space_used_fraction` (Number) Used fraction (used/total).
|
||||||
|
|
||||||
|
|
||||||
|
<a id="nestedatt--filters"></a>
|
||||||
|
### Nested Schema for `filters`
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
|
||||||
|
- `content_types` (Set of String) Only list stores with the given content types.
|
||||||
|
- `id` (String) Only list stores with the given ID.
|
||||||
|
- `target` (String) If `target` is different to `node_name`, then only lists shared stores which content is accessible on this node and the specified `target` node.
|
||||||
|
@ -55,7 +55,7 @@ func (r *aclResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
|||||||
stringplanmodifier.RequiresReplace(),
|
stringplanmodifier.RequiresReplace(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"path": schema.StringAttribute{
|
"path": schema.StringAttribute{
|
||||||
Description: "Access control path",
|
Description: "Access control path",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -76,7 +76,7 @@ func (r *userTokenResource) Schema(
|
|||||||
}, "must be a valid RFC3339 date"),
|
}, "must be a valid RFC3339 date"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"id": attribute.ID("Unique token identifier with format `<user_id>!<token_name>`."),
|
"id": attribute.ResourceID("Unique token identifier with format `<user_id>!<token_name>`."),
|
||||||
"privileges_separation": schema.BoolAttribute{
|
"privileges_separation": schema.BoolAttribute{
|
||||||
Description: "Restrict API token privileges with separate ACLs (default)",
|
Description: "Restrict API token privileges with separate ACLs (default)",
|
||||||
MarkdownDescription: "Restrict API token privileges with separate ACLs (default), " +
|
MarkdownDescription: "Restrict API token privileges with separate ACLs (default), " +
|
||||||
|
@ -13,8 +13,8 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ID generates an attribute definition suitable for the always-present `id` attribute.
|
// ResourceID generates an attribute definition suitable for the always-present resource `id` attribute.
|
||||||
func ID(desc ...string) schema.StringAttribute {
|
func ResourceID(desc ...string) schema.StringAttribute {
|
||||||
a := schema.StringAttribute{
|
a := schema.StringAttribute{
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "The unique identifier of this resource.",
|
Description: "The unique identifier of this resource.",
|
||||||
|
@ -51,7 +51,7 @@ func (d *haGroupDatasource) Schema(_ context.Context, _ datasource.SchemaRequest
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Retrieves information about a specific High Availability group.",
|
Description: "Retrieves information about a specific High Availability group.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"group": schema.StringAttribute{
|
"group": schema.StringAttribute{
|
||||||
Description: "The identifier of the High Availability group to read.",
|
Description: "The identifier of the High Availability group to read.",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -57,7 +57,7 @@ func (d *haGroupsDatasource) Schema(_ context.Context, _ datasource.SchemaReques
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Retrieves the list of High Availability groups.",
|
Description: "Retrieves the list of High Availability groups.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"group_ids": schema.SetAttribute{
|
"group_ids": schema.SetAttribute{
|
||||||
Description: "The identifiers of the High Availability groups.",
|
Description: "The identifiers of the High Availability groups.",
|
||||||
ElementType: types.StringType,
|
ElementType: types.StringType,
|
||||||
|
@ -50,7 +50,7 @@ func (d *haResourceDatasource) Schema(_ context.Context, _ datasource.SchemaRequ
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Retrieves the list of High Availability resources.",
|
Description: "Retrieves the list of High Availability resources.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"resource_id": schema.StringAttribute{
|
"resource_id": schema.StringAttribute{
|
||||||
Description: "The identifier of the Proxmox HA resource to read.",
|
Description: "The identifier of the Proxmox HA resource to read.",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -64,7 +64,7 @@ func (d *haResourcesDatasource) Schema(_ context.Context, _ datasource.SchemaReq
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Retrieves the list of High Availability resources.",
|
Description: "Retrieves the list of High Availability resources.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"type": schema.StringAttribute{
|
"type": schema.StringAttribute{
|
||||||
Description: "The type of High Availability resources to fetch (`vm` or `ct`). All resources " +
|
Description: "The type of High Availability resources to fetch (`vm` or `ct`). All resources " +
|
||||||
"will be fetched if this option is unset.",
|
"will be fetched if this option is unset.",
|
||||||
|
@ -64,7 +64,7 @@ func (r *hagroupResource) Schema(
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Manages a High Availability group in a Proxmox VE cluster.",
|
Description: "Manages a High Availability group in a Proxmox VE cluster.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"group": schema.StringAttribute{
|
"group": schema.StringAttribute{
|
||||||
Description: "The identifier of the High Availability group to manage.",
|
Description: "The identifier of the High Availability group to manage.",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -68,7 +68,7 @@ func (r *haResourceResource) Schema(
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Manages Proxmox HA resources.",
|
Description: "Manages Proxmox HA resources.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"resource_id": schema.StringAttribute{
|
"resource_id": schema.StringAttribute{
|
||||||
Description: "The Proxmox HA resource identifier",
|
Description: "The Proxmox HA resource identifier",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -71,7 +71,7 @@ func (r *metricsServerDatasource) Schema(
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Retrieves information about a specific PVE metric server.",
|
Description: "Retrieves information about a specific PVE metric server.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"name": schema.StringAttribute{
|
"name": schema.StringAttribute{
|
||||||
Description: "Unique name that will be ID of this metric server in PVE.",
|
Description: "Unique name that will be ID of this metric server in PVE.",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -79,7 +79,7 @@ func (r *metricsServerResource) Schema(
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Manages PVE metrics server.",
|
Description: "Manages PVE metrics server.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"name": schema.StringAttribute{
|
"name": schema.StringAttribute{
|
||||||
Description: "Unique name that will be ID of this metric server in PVE.",
|
Description: "Unique name that will be ID of this metric server in PVE.",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -457,7 +457,7 @@ func (r *clusterOptionsResource) Schema(
|
|||||||
resp.Schema = schema.Schema{
|
resp.Schema = schema.Schema{
|
||||||
Description: "Manages Proxmox VE Cluster Datacenter options.",
|
Description: "Manages Proxmox VE Cluster Datacenter options.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"email_from": schema.StringAttribute{
|
"email_from": schema.StringAttribute{
|
||||||
Description: "email address to send notification from (default is root@$hostname).",
|
Description: "email address to send notification from (default is root@$hostname).",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -153,7 +153,7 @@ func (d *repositoryDataSource) Schema(
|
|||||||
Description: "The list of package distributions.",
|
Description: "The list of package distributions.",
|
||||||
ElementType: types.StringType,
|
ElementType: types.StringType,
|
||||||
},
|
},
|
||||||
SchemaAttrNameTerraformID: attribute.ID("The unique identifier of this APT repository data source."),
|
SchemaAttrNameTerraformID: attribute.ResourceID("The unique identifier of this APT repository data source."),
|
||||||
SchemaAttrNameURIs: schema.ListAttribute{
|
SchemaAttrNameURIs: schema.ListAttribute{
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "The list of repository URIs.",
|
Description: "The list of repository URIs.",
|
||||||
|
@ -132,7 +132,7 @@ func (d *standardRepositoryDataSource) Schema(
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Indicates the activation status.",
|
Description: "Indicates the activation status.",
|
||||||
},
|
},
|
||||||
SchemaAttrNameTerraformID: attribute.ID(
|
SchemaAttrNameTerraformID: attribute.ResourceID(
|
||||||
"The unique identifier of this APT standard repository data source.",
|
"The unique identifier of this APT standard repository data source.",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -309,7 +309,7 @@ func (r *repositoryResource) Schema(_ context.Context, _ resource.SchemaRequest,
|
|||||||
Description: "The list of package distributions.",
|
Description: "The list of package distributions.",
|
||||||
ElementType: types.StringType,
|
ElementType: types.StringType,
|
||||||
},
|
},
|
||||||
SchemaAttrNameTerraformID: attribute.ID("The unique identifier of this APT repository resource."),
|
SchemaAttrNameTerraformID: attribute.ResourceID("The unique identifier of this APT repository resource."),
|
||||||
SchemaAttrNameURIs: schema.ListAttribute{
|
SchemaAttrNameURIs: schema.ListAttribute{
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "The list of repository URIs.",
|
Description: "The list of repository URIs.",
|
||||||
|
@ -275,7 +275,7 @@ func (r *standardRepositoryResource) Schema(
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "Indicates the activation status.",
|
Description: "Indicates the activation status.",
|
||||||
},
|
},
|
||||||
SchemaAttrNameTerraformID: attribute.ID(
|
SchemaAttrNameTerraformID: attribute.ResourceID(
|
||||||
"The unique identifier of this APT standard repository resource.",
|
"The unique identifier of this APT standard repository resource.",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
122
fwprovider/nodes/datastores/datasource.go
Normal file
122
fwprovider/nodes/datastores/datasource.go
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package datastores
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
|
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/config"
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/types/stringset"
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/proxmox"
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ensure the implementation satisfies the expected interfaces.
|
||||||
|
var (
|
||||||
|
_ datasource.DataSource = &Datasource{}
|
||||||
|
_ datasource.DataSourceWithConfigure = &Datasource{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Datasource is the implementation of datastores datasource.
|
||||||
|
type Datasource struct {
|
||||||
|
client proxmox.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDataSource creates a new datastores datasource.
|
||||||
|
func NewDataSource() datasource.DataSource {
|
||||||
|
return &Datasource{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata defines the name of the resource.
|
||||||
|
func (d *Datasource) Metadata(
|
||||||
|
_ context.Context,
|
||||||
|
req datasource.MetadataRequest,
|
||||||
|
resp *datasource.MetadataResponse,
|
||||||
|
) {
|
||||||
|
resp.TypeName = req.ProviderTypeName + "_datastores"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure sets the client for the resource.
|
||||||
|
func (d *Datasource) Configure(
|
||||||
|
_ context.Context,
|
||||||
|
req datasource.ConfigureRequest,
|
||||||
|
resp *datasource.ConfigureResponse,
|
||||||
|
) {
|
||||||
|
if req.ProviderData == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, ok := req.ProviderData.(config.DataSource)
|
||||||
|
if !ok {
|
||||||
|
resp.Diagnostics.AddError(
|
||||||
|
"Unexpected DataSource Configure Type",
|
||||||
|
fmt.Sprintf("Expected config.DataSource, got: %T", req.ProviderData),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d.client = cfg.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Datasource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
||||||
|
var model Model
|
||||||
|
|
||||||
|
resp.Diagnostics.Append(req.Config.Get(ctx, &model)...)
|
||||||
|
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
storageAPI := d.client.Node(model.NodeName.ValueString()).Storage("")
|
||||||
|
|
||||||
|
r := storage.DatastoreListRequestBody{}
|
||||||
|
if model.Filters != nil {
|
||||||
|
r.ContentTypes = model.Filters.ContentTypes.ValueList(ctx, &resp.Diagnostics)
|
||||||
|
r.ID = model.Filters.ID.ValueStringPointer()
|
||||||
|
r.Target = model.Filters.Target.ValueStringPointer()
|
||||||
|
}
|
||||||
|
|
||||||
|
dsList, err := storageAPI.ListDatastores(ctx, &r)
|
||||||
|
if err != nil {
|
||||||
|
resp.Diagnostics.AddError(
|
||||||
|
"Unable to read datastores",
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Datastores = make([]Datastore, 0, len(dsList))
|
||||||
|
|
||||||
|
for _, ds := range dsList {
|
||||||
|
datastore := Datastore{}
|
||||||
|
|
||||||
|
if ds.ContentTypes != nil {
|
||||||
|
datastore.ContentTypes = stringset.NewValueList(*ds.ContentTypes, &resp.Diagnostics)
|
||||||
|
}
|
||||||
|
|
||||||
|
datastore.Active = types.BoolPointerValue(ds.Active.PointerBool())
|
||||||
|
datastore.Enabled = types.BoolPointerValue(ds.Enabled.PointerBool())
|
||||||
|
datastore.ID = types.StringValue(ds.ID)
|
||||||
|
datastore.NodeName = types.StringValue(model.NodeName.ValueString())
|
||||||
|
datastore.Shared = types.BoolPointerValue(ds.Shared.PointerBool())
|
||||||
|
datastore.SpaceAvailable = types.Int64PointerValue(ds.SpaceAvailable.PointerInt64())
|
||||||
|
datastore.SpaceTotal = types.Int64PointerValue(ds.SpaceTotal.PointerInt64())
|
||||||
|
datastore.SpaceUsed = types.Int64PointerValue(ds.SpaceUsed.PointerInt64())
|
||||||
|
datastore.SpaceUsedFraction = types.Float64PointerValue(ds.SpaceUsedPercentage.PointerFloat64())
|
||||||
|
datastore.Type = types.StringValue(ds.Type)
|
||||||
|
|
||||||
|
model.Datastores = append(model.Datastores, datastore)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.Diagnostics.Append(resp.State.Set(ctx, model)...)
|
||||||
|
}
|
98
fwprovider/nodes/datastores/datasource_schema.go
Normal file
98
fwprovider/nodes/datastores/datasource_schema.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package datastores
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||||
|
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/types/stringset"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Schema defines the schema for the resource.
|
||||||
|
func (d *Datasource) Schema(
|
||||||
|
_ context.Context,
|
||||||
|
_ datasource.SchemaRequest,
|
||||||
|
resp *datasource.SchemaResponse,
|
||||||
|
) {
|
||||||
|
resp.Schema = schema.Schema{
|
||||||
|
Description: "Retrieves information about all the datastores available to a specific node.",
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"node_name": schema.StringAttribute{
|
||||||
|
Description: "The name of the node to retrieve the stores from.",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"filters": schema.SingleNestedAttribute{
|
||||||
|
Description: "The filters to apply to the stores.",
|
||||||
|
Optional: true,
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"content_types": stringset.DataSourceAttribute("Only list stores with the given content types.", "", true),
|
||||||
|
"id": schema.StringAttribute{
|
||||||
|
Description: "Only list stores with the given ID.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"target": schema.StringAttribute{
|
||||||
|
Description: "If `target` is different to `node_name`, then only lists shared stores which " +
|
||||||
|
"content is accessible on this node and the specified `target` node.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"datastores": schema.ListNestedAttribute{
|
||||||
|
Description: "The list of datastores.",
|
||||||
|
Optional: true,
|
||||||
|
NestedObject: schema.NestedAttributeObject{
|
||||||
|
Attributes: map[string]schema.Attribute{
|
||||||
|
"active": schema.BoolAttribute{
|
||||||
|
Description: "Whether the store is active.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"content_types": stringset.DataSourceAttribute("Allowed store content types.", "", false),
|
||||||
|
"enabled": schema.BoolAttribute{
|
||||||
|
Description: "Whether the store is enabled.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"id": schema.StringAttribute{
|
||||||
|
Description: "The ID of the store.",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"node_name": schema.StringAttribute{
|
||||||
|
Description: "The name of the node the store is on.",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"shared": schema.BoolAttribute{
|
||||||
|
Description: "Shared flag from store configuration.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"space_available": schema.Int64Attribute{
|
||||||
|
Description: "Available store space in bytes.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"space_total": schema.Int64Attribute{
|
||||||
|
Description: "Total store space in bytes.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"space_used": schema.Int64Attribute{
|
||||||
|
Description: "Used store space in bytes.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"space_used_fraction": schema.Float64Attribute{
|
||||||
|
Description: "Used fraction (used/total).",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"type": schema.StringAttribute{
|
||||||
|
Description: "Store type.",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
57
fwprovider/nodes/datastores/datasource_test.go
Normal file
57
fwprovider/nodes/datastores/datasource_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//go:build acceptance || all
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package datastores_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||||
|
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccDatasourceDatastores(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
te := test.InitEnvironment(t)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
steps []resource.TestStep
|
||||||
|
}{
|
||||||
|
{"read datastores attributes", []resource.TestStep{{
|
||||||
|
Config: te.RenderConfig(`data "proxmox_virtual_environment_datastores" "test" {
|
||||||
|
node_name = "{{.NodeName}}"
|
||||||
|
filters = {
|
||||||
|
content_types = ["iso"]
|
||||||
|
}
|
||||||
|
}`),
|
||||||
|
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
test.ResourceAttributesSet("data.proxmox_virtual_environment_datastores.test", []string{
|
||||||
|
"node_name",
|
||||||
|
}),
|
||||||
|
test.ResourceAttributes("data.proxmox_virtual_environment_datastores.test", map[string]string{
|
||||||
|
"datastores.#": "1",
|
||||||
|
"datastores.0.active": "true",
|
||||||
|
"datastores.0.id": "local",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
resource.ParallelTest(t, resource.TestCase{
|
||||||
|
ProtoV6ProviderFactories: te.AccProviders,
|
||||||
|
Steps: tt.steps,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
37
fwprovider/nodes/datastores/model.go
Normal file
37
fwprovider/nodes/datastores/model.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package datastores
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||||
|
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/types/stringset"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Model struct {
|
||||||
|
NodeName types.String `tfsdk:"node_name"`
|
||||||
|
Filters *struct {
|
||||||
|
ContentTypes stringset.Value `tfsdk:"content_types"`
|
||||||
|
ID types.String `tfsdk:"id"`
|
||||||
|
Target types.String `tfsdk:"target"`
|
||||||
|
} `tfsdk:"filters"`
|
||||||
|
Datastores []Datastore `tfsdk:"datastores"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Datastore struct {
|
||||||
|
Active types.Bool `tfsdk:"active"`
|
||||||
|
ContentTypes stringset.Value `tfsdk:"content_types"`
|
||||||
|
Enabled types.Bool `tfsdk:"enabled"`
|
||||||
|
ID types.String `tfsdk:"id"`
|
||||||
|
NodeName types.String `tfsdk:"node_name"`
|
||||||
|
Shared types.Bool `tfsdk:"shared"`
|
||||||
|
SpaceAvailable types.Int64 `tfsdk:"space_available"`
|
||||||
|
SpaceTotal types.Int64 `tfsdk:"space_total"`
|
||||||
|
SpaceUsed types.Int64 `tfsdk:"space_used"`
|
||||||
|
SpaceUsedFraction types.Float64 `tfsdk:"space_used_fraction"`
|
||||||
|
Type types.String `tfsdk:"type"`
|
||||||
|
}
|
@ -179,7 +179,7 @@ func (d *dataSource) Schema(
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "The identifiers of the hardware mappings.",
|
Description: "The identifiers of the hardware mappings.",
|
||||||
},
|
},
|
||||||
schemaAttrNameTerraformID: attribute.ID(
|
schemaAttrNameTerraformID: attribute.ResourceID(
|
||||||
"The unique identifier of this hardware mappings data source.",
|
"The unique identifier of this hardware mappings data source.",
|
||||||
),
|
),
|
||||||
schemaAttrNameType: schema.StringAttribute{
|
schemaAttrNameType: schema.StringAttribute{
|
||||||
|
@ -155,7 +155,7 @@ func (d *pciDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, re
|
|||||||
Description: "The name of this PCI hardware mapping.",
|
Description: "The name of this PCI hardware mapping.",
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
schemaAttrNameTerraformID: attribute.ID(
|
schemaAttrNameTerraformID: attribute.ResourceID(
|
||||||
"The unique identifier of this PCI hardware mapping data source.",
|
"The unique identifier of this PCI hardware mapping data source.",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -137,7 +137,7 @@ func (d *usbDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, re
|
|||||||
Description: "The name of this USB hardware mapping.",
|
Description: "The name of this USB hardware mapping.",
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
schemaAttrNameTerraformID: attribute.ID(
|
schemaAttrNameTerraformID: attribute.ResourceID(
|
||||||
"The unique identifier of this USB hardware mapping data source.",
|
"The unique identifier of this USB hardware mapping data source.",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -266,7 +266,7 @@ func (r *pciResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
|||||||
Description: "The name of this PCI hardware mapping.",
|
Description: "The name of this PCI hardware mapping.",
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
schemaAttrNameTerraformID: attribute.ID(
|
schemaAttrNameTerraformID: attribute.ResourceID(
|
||||||
"The unique identifier of this PCI hardware mapping resource.",
|
"The unique identifier of this PCI hardware mapping resource.",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -250,7 +250,7 @@ func (r *usbResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *
|
|||||||
Description: "The name of this hardware mapping.",
|
Description: "The name of this hardware mapping.",
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
schemaAttrNameTerraformID: attribute.ID(
|
schemaAttrNameTerraformID: attribute.ResourceID(
|
||||||
"The unique identifier of this USB hardware mapping resource.",
|
"The unique identifier of this USB hardware mapping resource.",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -174,7 +174,7 @@ func (r *linuxBridgeResource) Schema(
|
|||||||
Description: "Manages a Linux Bridge network interface in a Proxmox VE node.",
|
Description: "Manages a Linux Bridge network interface in a Proxmox VE node.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
// Base attributes
|
// Base attributes
|
||||||
"id": attribute.ID("A unique identifier with format `<node name>:<iface>`"),
|
"id": attribute.ResourceID("A unique identifier with format `<node name>:<iface>`"),
|
||||||
"node_name": schema.StringAttribute{
|
"node_name": schema.StringAttribute{
|
||||||
Description: "The name of the node.",
|
Description: "The name of the node.",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -147,7 +147,7 @@ func (r *linuxVLANResource) Schema(
|
|||||||
Description: "Manages a Linux VLAN network interface in a Proxmox VE node.",
|
Description: "Manages a Linux VLAN network interface in a Proxmox VE node.",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
// Base attributes
|
// Base attributes
|
||||||
"id": attribute.ID("A unique identifier with format `<node name>:<iface>`."),
|
"id": attribute.ResourceID("A unique identifier with format `<node name>:<iface>`."),
|
||||||
"node_name": schema.StringAttribute{
|
"node_name": schema.StringAttribute{
|
||||||
Description: "The name of the node.",
|
Description: "The name of the node.",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -190,7 +190,7 @@ func (r *downloadFileResource) Schema(
|
|||||||
"It can be fully compatible and faster replacement for image files created using " +
|
"It can be fully compatible and faster replacement for image files created using " +
|
||||||
"`proxmox_virtual_environment_file`. Supports images for VMs (ISO images) and LXC (CT Templates).",
|
"`proxmox_virtual_environment_file`. Supports images for VMs (ISO images) and LXC (CT Templates).",
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"id": attribute.ID(),
|
"id": attribute.ResourceID(),
|
||||||
"content_type": schema.StringAttribute{
|
"content_type": schema.StringAttribute{
|
||||||
Description: "The file content type. Must be `iso` for VM images or `vztmpl` for LXC images.",
|
Description: "The file content type. Must be `iso` for VM images or `vztmpl` for LXC images.",
|
||||||
Required: true,
|
Required: true,
|
||||||
|
@ -82,7 +82,7 @@ func read(ctx context.Context, client proxmox.Client, model *Model, diags *diag.
|
|||||||
// Optional fields can be removed from the model, use StringPointerValue to handle removal on nil
|
// Optional fields can be removed from the model, use StringPointerValue to handle removal on nil
|
||||||
model.Description = types.StringPointerValue(config.Description)
|
model.Description = types.StringPointerValue(config.Description)
|
||||||
model.Name = types.StringPointerValue(config.Name)
|
model.Name = types.StringPointerValue(config.Name)
|
||||||
model.Tags = stringset.NewValue(config.Tags, diags)
|
model.Tags = stringset.NewValueString(config.Tags, diags)
|
||||||
model.Template = types.BoolPointerValue(config.Template.PointerBool())
|
model.Template = types.BoolPointerValue(config.Template.PointerBool())
|
||||||
|
|
||||||
// Blocks
|
// Blocks
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
"github.com/bpg/terraform-provider-proxmox/fwprovider/config"
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/config"
|
||||||
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes"
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes"
|
||||||
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/apt"
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/apt"
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/datastores"
|
||||||
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/hardwaremapping"
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/hardwaremapping"
|
||||||
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/network"
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/network"
|
||||||
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/vm"
|
"github.com/bpg/terraform-provider-proxmox/fwprovider/nodes/vm"
|
||||||
@ -525,6 +526,7 @@ func (p *proxmoxProvider) DataSources(_ context.Context) []func() datasource.Dat
|
|||||||
acme.NewACMEPluginsDataSource,
|
acme.NewACMEPluginsDataSource,
|
||||||
apt.NewRepositoryDataSource,
|
apt.NewRepositoryDataSource,
|
||||||
apt.NewStandardRepositoryDataSource,
|
apt.NewStandardRepositoryDataSource,
|
||||||
|
datastores.NewDataSource,
|
||||||
ha.NewHAGroupDataSource,
|
ha.NewHAGroupDataSource,
|
||||||
ha.NewHAGroupsDataSource,
|
ha.NewHAGroupsDataSource,
|
||||||
ha.NewHAResourceDataSource,
|
ha.NewHAResourceDataSource,
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
package stringset
|
package stringset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -24,7 +30,7 @@ func ResourceAttribute(desc, markdownDesc string) schema.SetAttribute {
|
|||||||
Computed: true,
|
Computed: true,
|
||||||
ElementType: types.StringType,
|
ElementType: types.StringType,
|
||||||
Validators: []validator.Set{
|
Validators: []validator.Set{
|
||||||
// NOTE: we allow empty list to remove all previously set tags
|
// NOTE: we allow empty list to remove all previously set values
|
||||||
setvalidator.ValueStringsAre(
|
setvalidator.ValueStringsAre(
|
||||||
stringvalidator.RegexMatches(
|
stringvalidator.RegexMatches(
|
||||||
regexp.MustCompile(`(.|\s)*\S(.|\s)*`),
|
regexp.MustCompile(`(.|\s)*\S(.|\s)*`),
|
||||||
@ -35,3 +41,25 @@ func ResourceAttribute(desc, markdownDesc string) schema.SetAttribute {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DataSourceAttribute returns a data source schema attribute for string set.
|
||||||
|
func DataSourceAttribute(desc, markdownDesc string, optional bool) schema.SetAttribute {
|
||||||
|
attribute := schema.SetAttribute{
|
||||||
|
CustomType: Type{
|
||||||
|
SetType: types.SetType{
|
||||||
|
ElemType: types.StringType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Description: desc,
|
||||||
|
MarkdownDescription: markdownDesc,
|
||||||
|
ElementType: types.StringType,
|
||||||
|
}
|
||||||
|
|
||||||
|
if optional {
|
||||||
|
attribute.Optional = true
|
||||||
|
} else {
|
||||||
|
attribute.Required = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return attribute
|
||||||
|
}
|
||||||
|
38
fwprovider/types/stringset/options.go
Normal file
38
fwprovider/types/stringset/options.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package stringset
|
||||||
|
|
||||||
|
type options struct {
|
||||||
|
separator string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Option struct {
|
||||||
|
apply func(*options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultOptions(opts ...Option) options {
|
||||||
|
opt := options{
|
||||||
|
separator: ";",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range opts {
|
||||||
|
o.apply(&opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return opt
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithSeparator sets the separator for the string set value.
|
||||||
|
// For future use, to set the separator to a different value than the default ";".
|
||||||
|
// Would allow us to replace types.CustomCommaSeparatedList custom type that can only handle commas.
|
||||||
|
func WithSeparator(separator string) Option {
|
||||||
|
return Option{
|
||||||
|
apply: func(o *options) {
|
||||||
|
o.separator = separator
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
package stringset
|
package stringset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -40,8 +46,8 @@ func (v Value) Equal(o attr.Value) bool {
|
|||||||
return v.SetValue.Equal(other.SetValue)
|
return v.SetValue.Equal(other.SetValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueStringPointer returns a pointer to the string representation of string set value.
|
// ValueList returns a string slice of set value.
|
||||||
func (v Value) ValueStringPointer(ctx context.Context, diags *diag.Diagnostics) *string {
|
func (v Value) ValueList(ctx context.Context, diags *diag.Diagnostics) []string {
|
||||||
if v.IsNull() || v.IsUnknown() || len(v.Elements()) == 0 {
|
if v.IsNull() || v.IsUnknown() || len(v.Elements()) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -67,16 +73,27 @@ func (v Value) ValueStringPointer(ctx context.Context, diags *diag.Diagnostics)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr.Ptr(strings.Join(sanitizedItems, ";"))
|
return sanitizedItems
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewValue converts a string of items to a new string set value.
|
// ValueStringPointer returns a pointer to the string representation of string set value.
|
||||||
func NewValue(str *string, diags *diag.Diagnostics) Value {
|
func (v Value) ValueStringPointer(ctx context.Context, diags *diag.Diagnostics, opts ...Option) *string {
|
||||||
if str == nil {
|
elems := v.ValueList(ctx, diags)
|
||||||
|
if len(elems) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
o := defaultOptions(opts...)
|
||||||
|
|
||||||
|
return ptr.Ptr(strings.Join(elems, o.separator))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewValueList converts a slice of items to a new string set value.
|
||||||
|
func NewValueList(items []string, diags *diag.Diagnostics) Value {
|
||||||
|
if len(items) == 0 {
|
||||||
return Value{types.SetValueMust(types.StringType, []attr.Value{})}
|
return Value{types.SetValueMust(types.StringType, []attr.Value{})}
|
||||||
}
|
}
|
||||||
|
|
||||||
items := strings.Split(*str, ";")
|
|
||||||
elems := make([]attr.Value, len(items))
|
elems := make([]attr.Value, len(items))
|
||||||
|
|
||||||
for i, item := range items {
|
for i, item := range items {
|
||||||
@ -88,3 +105,16 @@ func NewValue(str *string, diags *diag.Diagnostics) Value {
|
|||||||
|
|
||||||
return Value{setValue}
|
return Value{setValue}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewValueString converts a string of items to a new string set value.
|
||||||
|
func NewValueString(str *string, diags *diag.Diagnostics, opts ...Option) Value {
|
||||||
|
if str == nil || *str == "" {
|
||||||
|
return Value{types.SetValueMust(types.StringType, []attr.Value{})}
|
||||||
|
}
|
||||||
|
|
||||||
|
o := defaultOptions(opts...)
|
||||||
|
|
||||||
|
items := strings.Split(*str, o.separator)
|
||||||
|
|
||||||
|
return NewValueList(items, diags)
|
||||||
|
}
|
||||||
|
1
main.go
1
main.go
@ -39,6 +39,7 @@ import (
|
|||||||
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_acme_plugins.md ./docs/data-sources/
|
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_acme_plugins.md ./docs/data-sources/
|
||||||
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_apt_repository.md ./docs/data-sources/
|
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_apt_repository.md ./docs/data-sources/
|
||||||
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_apt_standard_repository.md ./docs/data-sources/
|
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_apt_standard_repository.md ./docs/data-sources/
|
||||||
|
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_datastores.md ./docs/data-sources/
|
||||||
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_hagroup.md ./docs/data-sources/
|
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_hagroup.md ./docs/data-sources/
|
||||||
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_hagroups.md ./docs/data-sources/
|
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_hagroups.md ./docs/data-sources/
|
||||||
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_hardware_mapping_pci.md ./docs/data-sources/
|
//go:generate cp ./build/docs-gen/data-sources/virtual_environment_hardware_mapping_pci.md ./docs/data-sources/
|
||||||
|
@ -31,9 +31,9 @@ type DatastoreListResponseData struct {
|
|||||||
Enabled *types.CustomBool `json:"enabled,omitempty"`
|
Enabled *types.CustomBool `json:"enabled,omitempty"`
|
||||||
ID string `json:"storage,omitempty"`
|
ID string `json:"storage,omitempty"`
|
||||||
Shared *types.CustomBool `json:"shared,omitempty"`
|
Shared *types.CustomBool `json:"shared,omitempty"`
|
||||||
SpaceAvailable *int `json:"avail,omitempty"`
|
SpaceAvailable *types.CustomInt64 `json:"avail,omitempty"`
|
||||||
SpaceTotal *int `json:"total,omitempty"`
|
SpaceTotal *types.CustomInt64 `json:"total,omitempty"`
|
||||||
SpaceUsed *int `json:"used,omitempty"`
|
SpaceUsed *types.CustomInt64 `json:"used,omitempty"`
|
||||||
SpaceUsedPercentage *float64 `json:"used_fraction,omitempty"`
|
SpaceUsedPercentage *types.CustomFloat64 `json:"used_fraction,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,9 @@ type CustomBool bool
|
|||||||
// CustomCommaSeparatedList allows a JSON string to also be a string array.
|
// CustomCommaSeparatedList allows a JSON string to also be a string array.
|
||||||
type CustomCommaSeparatedList []string
|
type CustomCommaSeparatedList []string
|
||||||
|
|
||||||
|
// CustomFloat64 allows a JSON float64 value to also be a string.
|
||||||
|
type CustomFloat64 float64
|
||||||
|
|
||||||
// CustomInt allows a JSON integer value to also be a string.
|
// CustomInt allows a JSON integer value to also be a string.
|
||||||
type CustomInt int
|
type CustomInt int
|
||||||
|
|
||||||
@ -111,6 +114,29 @@ func (r *CustomCommaSeparatedList) UnmarshalJSON(b []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON converts a JSON value to a float64 value.
|
||||||
|
func (r *CustomFloat64) UnmarshalJSON(b []byte) error {
|
||||||
|
s := string(b)
|
||||||
|
|
||||||
|
if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") {
|
||||||
|
s = s[1 : len(s)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := strconv.ParseFloat(s, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot parse float64 %q: %w", s, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
*r = CustomFloat64(f)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PointerFloat64 returns a pointer to a float64.
|
||||||
|
func (r *CustomFloat64) PointerFloat64() *float64 {
|
||||||
|
return (*float64)(r)
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON converts a JSON value to an integer.
|
// UnmarshalJSON converts a JSON value to an integer.
|
||||||
func (r *CustomInt) UnmarshalJSON(b []byte) error {
|
func (r *CustomInt) UnmarshalJSON(b []byte) error {
|
||||||
s := string(b)
|
s := string(b)
|
||||||
|
@ -1,201 +0,0 @@
|
|||||||
/*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package datasource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"sort"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresActive = "active"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresContentTypes = "content_types"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresDatastoreIDs = "datastore_ids"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresEnabled = "enabled"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresNodeName = "node_name"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresShared = "shared"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceAvailable = "space_available"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceTotal = "space_total"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceUsed = "space_used"
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresTypes = "types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Datastores returns a resource for the Proxmox data store.
|
|
||||||
func Datastores() *schema.Resource {
|
|
||||||
return &schema.Resource{
|
|
||||||
Schema: map[string]*schema.Schema{
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresActive: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "Whether a datastore is active",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeBool},
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresContentTypes: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "The allowed content types",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresDatastoreIDs: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "The datastore id",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresEnabled: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "Whether a datastore is enabled",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeBool},
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresNodeName: {
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Description: "The node name",
|
|
||||||
Required: true,
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresShared: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "Whether a datastore is shared",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeBool},
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceAvailable: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "The available space in bytes",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeInt},
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceTotal: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "The total space in bytes",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeInt},
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceUsed: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "The used space in bytes",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeInt},
|
|
||||||
},
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresTypes: {
|
|
||||||
Type: schema.TypeList,
|
|
||||||
Description: "The storage type",
|
|
||||||
Computed: true,
|
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ReadContext: datastoresRead,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func datastoresRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
|
|
||||||
var diags diag.Diagnostics
|
|
||||||
|
|
||||||
config := m.(proxmoxtf.ProviderConfiguration)
|
|
||||||
api, err := config.GetClient()
|
|
||||||
if err != nil {
|
|
||||||
return diag.FromErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeName := d.Get(mkDataSourceVirtualEnvironmentDatastoresNodeName).(string)
|
|
||||||
list, err := api.Node(nodeName).Storage("").ListDatastores(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return diag.FromErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
active := make([]interface{}, len(list))
|
|
||||||
contentTypes := make([]interface{}, len(list))
|
|
||||||
datastoreIDs := make([]interface{}, len(list))
|
|
||||||
enabled := make([]interface{}, len(list))
|
|
||||||
shared := make([]interface{}, len(list))
|
|
||||||
spaceAvailable := make([]interface{}, len(list))
|
|
||||||
spaceTotal := make([]interface{}, len(list))
|
|
||||||
spaceUsed := make([]interface{}, len(list))
|
|
||||||
types := make([]interface{}, len(list))
|
|
||||||
|
|
||||||
for i, v := range list {
|
|
||||||
if v.Active != nil {
|
|
||||||
active[i] = bool(*v.Active)
|
|
||||||
} else {
|
|
||||||
active[i] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.ContentTypes != nil {
|
|
||||||
contentTypeList := []string(*v.ContentTypes)
|
|
||||||
sort.Strings(contentTypeList)
|
|
||||||
contentTypes[i] = contentTypeList
|
|
||||||
} else {
|
|
||||||
contentTypes[i] = []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
datastoreIDs[i] = v.ID
|
|
||||||
|
|
||||||
if v.Enabled != nil {
|
|
||||||
enabled[i] = bool(*v.Enabled)
|
|
||||||
} else {
|
|
||||||
enabled[i] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Shared != nil {
|
|
||||||
shared[i] = bool(*v.Shared)
|
|
||||||
} else {
|
|
||||||
shared[i] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.SpaceAvailable != nil {
|
|
||||||
spaceAvailable[i] = *v.SpaceAvailable
|
|
||||||
} else {
|
|
||||||
spaceAvailable[i] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.SpaceTotal != nil {
|
|
||||||
spaceTotal[i] = *v.SpaceTotal
|
|
||||||
} else {
|
|
||||||
spaceTotal[i] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.SpaceUsed != nil {
|
|
||||||
spaceUsed[i] = *v.SpaceUsed
|
|
||||||
} else {
|
|
||||||
spaceUsed[i] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
types[i] = v.Type
|
|
||||||
}
|
|
||||||
|
|
||||||
d.SetId(fmt.Sprintf("%s_datastores", nodeName))
|
|
||||||
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresActive, active)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresContentTypes, contentTypes)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresDatastoreIDs, datastoreIDs)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresEnabled, enabled)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresShared, shared)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresSpaceAvailable, spaceAvailable)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresSpaceTotal, spaceTotal)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresSpaceUsed, spaceUsed)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
err = d.Set(mkDataSourceVirtualEnvironmentDatastoresTypes, types)
|
|
||||||
diags = append(diags, diag.FromErr(err)...)
|
|
||||||
|
|
||||||
return diags
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package datasource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestDatastoresInstantiation tests whether the Datastores instance can be instantiated.
|
|
||||||
func TestDatastoresInstantiation(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
s := Datastores()
|
|
||||||
if s == nil {
|
|
||||||
t.Fatalf("Cannot instantiate Datastores")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestDatastoresSchema tests the Datastores schema.
|
|
||||||
func TestDatastoresSchema(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
s := Datastores().Schema
|
|
||||||
|
|
||||||
test.AssertRequiredArguments(t, s, []string{
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresNodeName,
|
|
||||||
})
|
|
||||||
|
|
||||||
test.AssertComputedAttributes(t, s, []string{
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresActive,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresContentTypes,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresDatastoreIDs,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresEnabled,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresShared,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceAvailable,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceTotal,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceUsed,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresTypes,
|
|
||||||
})
|
|
||||||
|
|
||||||
test.AssertValueTypes(t, s, map[string]schema.ValueType{
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresActive: schema.TypeList,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresContentTypes: schema.TypeList,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresDatastoreIDs: schema.TypeList,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresEnabled: schema.TypeList,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresNodeName: schema.TypeString,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresShared: schema.TypeList,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceAvailable: schema.TypeList,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceTotal: schema.TypeList,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresSpaceUsed: schema.TypeList,
|
|
||||||
mkDataSourceVirtualEnvironmentDatastoresTypes: schema.TypeList,
|
|
||||||
})
|
|
||||||
}
|
|
@ -14,22 +14,21 @@ import (
|
|||||||
|
|
||||||
func createDatasourceMap() map[string]*schema.Resource {
|
func createDatasourceMap() map[string]*schema.Resource {
|
||||||
return map[string]*schema.Resource{
|
return map[string]*schema.Resource{
|
||||||
"proxmox_virtual_environment_datastores": datasource.Datastores(),
|
"proxmox_virtual_environment_dns": datasource.DNS(),
|
||||||
"proxmox_virtual_environment_dns": datasource.DNS(),
|
"proxmox_virtual_environment_group": datasource.Group(),
|
||||||
"proxmox_virtual_environment_group": datasource.Group(),
|
"proxmox_virtual_environment_groups": datasource.Groups(),
|
||||||
"proxmox_virtual_environment_groups": datasource.Groups(),
|
"proxmox_virtual_environment_hosts": datasource.Hosts(),
|
||||||
"proxmox_virtual_environment_hosts": datasource.Hosts(),
|
"proxmox_virtual_environment_node": datasource.Node(),
|
||||||
"proxmox_virtual_environment_node": datasource.Node(),
|
"proxmox_virtual_environment_nodes": datasource.Nodes(),
|
||||||
"proxmox_virtual_environment_nodes": datasource.Nodes(),
|
"proxmox_virtual_environment_pool": datasource.Pool(),
|
||||||
"proxmox_virtual_environment_pool": datasource.Pool(),
|
"proxmox_virtual_environment_pools": datasource.Pools(),
|
||||||
"proxmox_virtual_environment_pools": datasource.Pools(),
|
"proxmox_virtual_environment_role": datasource.Role(),
|
||||||
"proxmox_virtual_environment_role": datasource.Role(),
|
"proxmox_virtual_environment_roles": datasource.Roles(),
|
||||||
"proxmox_virtual_environment_roles": datasource.Roles(),
|
"proxmox_virtual_environment_time": datasource.Time(),
|
||||||
"proxmox_virtual_environment_time": datasource.Time(),
|
"proxmox_virtual_environment_user": datasource.User(),
|
||||||
"proxmox_virtual_environment_user": datasource.User(),
|
"proxmox_virtual_environment_users": datasource.Users(),
|
||||||
"proxmox_virtual_environment_users": datasource.Users(),
|
"proxmox_virtual_environment_vm": datasource.VM(),
|
||||||
"proxmox_virtual_environment_vm": datasource.VM(),
|
"proxmox_virtual_environment_vms": datasource.VMs(),
|
||||||
"proxmox_virtual_environment_vms": datasource.VMs(),
|
"proxmox_virtual_environment_container": datasource.Container(),
|
||||||
"proxmox_virtual_environment_container": datasource.Container(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user