Skip to content

Commit

Permalink
Implement Cluster Datasource (#6)
Browse files Browse the repository at this point in the history
Add Cluster Acs Detail of version 14
Improve CopyFields() to match with tags in case of name unmatched
Remove config log in provider test
  • Loading branch information
NavisJ authored Jul 31, 2023
1 parent ff2e01a commit 7aefdef
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 35 deletions.
14 changes: 14 additions & 0 deletions docs/data-sources/cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,26 @@ The cluster attributes and cluster node information.

### Read-Only

- `acs` (Attributes) V14ClusterAcs Cluster ACS status. (see [below for nested schema](#nestedatt--acs))
- `config` (Attributes) The configuration information of cluster. (see [below for nested schema](#nestedatt--config))
- `id` (String) Unique identifier of the cluster.
- `identity` (Attributes) Unprivileged cluster information for display when logging in. (see [below for nested schema](#nestedatt--identity))
- `internal_networks` (Attributes) V7ClusterInternalNetworks Configuration fields for internal networks. (see [below for nested schema](#nestedatt--internal_networks))
- `nodes` (Attributes) IsiClusterNodes struct for IsiClusterNodes (see [below for nested schema](#nestedatt--nodes))

<a id="nestedatt--acs"></a>
### Nested Schema for `acs`

Read-Only:

- `failed_nodes_sn` (List of String) list of failed nodes serial number.
- `joined_nodes` (Number) the number of joined nodes.
- `license_status` (String) the status of license activation.
- `srs_status` (String) the status of SRS enablement.
- `total_nodes` (Number) total nodes number of the cluster.
- `unresponsive_sn` (List of String) list of unresponsive nodes serial number.


<a id="nestedatt--config"></a>
### Nested Schema for `config`

Expand Down
12 changes: 6 additions & 6 deletions powerscale/helper/access_zone_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
)

// AccessZoneDetailMapper Does the mapping from response to model
// AccessZoneDetailMapper Does the mapping from response to model.
func AccessZoneDetailMapper(ctx context.Context, az *powerscale.V3ZoneExtended) (models.AccessZoneDetailModel, error) {
model := models.AccessZoneDetailModel{}
err := CopyFields(ctx, az, &model)
Expand All @@ -46,7 +46,7 @@ func AccessZoneDetailMapper(ctx context.Context, az *powerscale.V3ZoneExtended)
return model, nil
}

// AccessZoneResouceDetailMapper detail mapper for access zone resource
// AccessZoneResouceDetailMapper detail mapper for access zone resource.
func AccessZoneResouceDetailMapper(ctx context.Context, az *powerscale.V3ZoneExtended) (models.AccessZoneResourceModel, error) {
model := models.AccessZoneResourceModel{}
err := CopyFields(ctx, az, &model)
Expand Down Expand Up @@ -79,13 +79,13 @@ func GetAuthAccessKeyObjects(accessResponse []powerscale.V1AuthAccessAccessItemF
return types.ListValue(types.ObjectType{AttrTypes: accessType}, accessKeyObjects)
}

// GetAllAccessZones returns the full list of access zones
// GetAllAccessZones returns the full list of access zones.
func GetAllAccessZones(ctx context.Context, client *client.Client) (*powerscale.V3Zones, error) {
result, _, err := client.PscaleOpenAPIClient.ZonesApi.ListZonesv3Zones(ctx).Execute()
return result, err
}

// CreateAccessZones Creates an Access Zone
// CreateAccessZones Creates an Access Zone.
func CreateAccessZones(ctx context.Context, client *client.Client, authProv []string, plan *models.AccessZoneResourceModel) error {
forceOverlap := true
createPath := false
Expand All @@ -103,7 +103,7 @@ func CreateAccessZones(ctx context.Context, client *client.Client, authProv []st
return err
}

// GetSpecificZone returns a specific zone or an error
// GetSpecificZone returns a specific zone or an error.
func GetSpecificZone(ctx context.Context, matchZone string, zoneList []powerscale.V3ZoneExtended) (models.AccessZoneResourceModel, error) {
for _, vze := range zoneList {
if *vze.Name == matchZone {
Expand All @@ -122,7 +122,7 @@ func GetSpecificZone(ctx context.Context, matchZone string, zoneList []powerscal
return models.AccessZoneResourceModel{}, fmt.Errorf("error finding new access zone after create, Unable to create successfully")
}

// ExtractCustomAuthForInput extracts the custom auth provider from actual auth provider for input
// ExtractCustomAuthForInput extracts the custom auth provider from actual auth provider for input.
func ExtractCustomAuthForInput(ctx context.Context, authProv basetypes.ListValue, mainAuth string) (basetypes.ListValue, diag.Diagnostics) {
var filteredAuths []attr.Value
for _, v := range authProv.Elements() {
Expand Down
74 changes: 60 additions & 14 deletions powerscale/helper/cluster_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
)

// GetClusterConfigSchema Get cluster config schema
// GetClusterConfigSchema Get cluster config schema.
func GetClusterConfigSchema() schema.Attribute {
config := schema.SingleNestedAttribute{
return schema.SingleNestedAttribute{
MarkdownDescription: "The configuration information of cluster.",
Description: "The configuration information of cluster.",
Computed: true,
Expand Down Expand Up @@ -142,10 +142,9 @@ func GetClusterConfigSchema() schema.Attribute {
},
},
}
return config
}

// GetClusterIdentitySchema Get cluster identity schema
// GetClusterIdentitySchema Get cluster identity schema.
func GetClusterIdentitySchema() schema.Attribute {
identity := schema.SingleNestedAttribute{
MarkdownDescription: "Unprivileged cluster information for display when logging in.",
Expand Down Expand Up @@ -184,9 +183,9 @@ func GetClusterIdentitySchema() schema.Attribute {
return identity
}

// GetClusterNodeSchema get cluster node schema
// GetClusterNodeSchema get cluster node schema.
func GetClusterNodeSchema() schema.Attribute {
attribute := schema.SingleNestedAttribute{
return schema.SingleNestedAttribute{
MarkdownDescription: "IsiClusterNodes struct for IsiClusterNodes",
Description: "IsiClusterNodes struct for IsiClusterNodes",
Computed: true,
Expand Down Expand Up @@ -1083,12 +1082,11 @@ func GetClusterNodeSchema() schema.Attribute {
},
},
}
return attribute
}

// GetClusterInternalNetworksSchema get cluster internal network schema
// GetClusterInternalNetworksSchema get cluster internal network schema.
func GetClusterInternalNetworksSchema() schema.Attribute {
networks := schema.SingleNestedAttribute{
return schema.SingleNestedAttribute{
// This description is used by the documentation generator and the language server.
MarkdownDescription: "V7ClusterInternalNetworks Configuration fields for internal networks.",
Description: "V7ClusterInternalNetworks Configuration fields for internal networks.",
Expand Down Expand Up @@ -1193,29 +1191,77 @@ func GetClusterInternalNetworksSchema() schema.Attribute {
},
},
}
return networks
}

// GetClusterConfig retrieve the cluster information
// GetClusterAcsSchema get cluster internal network schema.
func GetClusterAcsSchema() schema.Attribute {
return schema.SingleNestedAttribute{
MarkdownDescription: "V14ClusterAcs Cluster ACS status.",
Description: "V14ClusterAcs Cluster ACS status.",
Computed: true,
Attributes: map[string]schema.Attribute{
"failed_nodes_sn": schema.ListAttribute{
Description: "list of failed nodes serial number.",
MarkdownDescription: "list of failed nodes serial number.",
Computed: true,
ElementType: types.StringType,
},
"joined_nodes": schema.Int64Attribute{
Description: "the number of joined nodes.",
MarkdownDescription: "the number of joined nodes.",
Computed: true,
},
"license_status": schema.StringAttribute{
Description: "the status of license activation.",
MarkdownDescription: "the status of license activation.",
Computed: true,
},
"srs_status": schema.StringAttribute{
Description: "the status of SRS enablement.",
MarkdownDescription: "the status of SRS enablement.",
Computed: true,
},
"total_nodes": schema.Int64Attribute{
Description: "total nodes number of the cluster.",
MarkdownDescription: "total nodes number of the cluster.",
Computed: true,
},
"unresponsive_sn": schema.ListAttribute{
Description: "list of unresponsive nodes serial number.",
MarkdownDescription: "list of unresponsive nodes serial number.",
Computed: true,
ElementType: types.StringType,
},
},
}
}

// GetClusterConfig retrieve the cluster information.
func GetClusterConfig(ctx context.Context, client *client.Client) (*powerscale.V3ClusterConfig, error) {
config, _, err := client.PscaleOpenAPIClient.ClusterApi.GetClusterv3ClusterConfig(ctx).Execute()
return config, err
}

// GetClusterIdentity retrieve the login information
// GetClusterIdentity retrieve the login information.
func GetClusterIdentity(ctx context.Context, client *client.Client) (*powerscale.V1ClusterIdentity, error) {
identity, _, err := client.PscaleOpenAPIClient.ClusterApi.GetClusterv3ClusterIdentity(ctx).Execute()
return identity, err
}

// GetClusterNodes list the nodes on this cluster
// GetClusterNodes list the nodes on this cluster.
func GetClusterNodes(ctx context.Context, client *client.Client) (*powerscale.V3ClusterNodes, error) {
nodes, _, err := client.PscaleOpenAPIClient.ClusterApi.GetClusterv3ClusterNodes(ctx).Execute()
return nodes, err
}

// GetClusterInternalNetworks list internal networks settings
// GetClusterInternalNetworks list internal networks settings.
func GetClusterInternalNetworks(ctx context.Context, client *client.Client) (*powerscale.V7ClusterInternalNetworks, error) {
networks, _, err := client.PscaleOpenAPIClient.ClusterApi.GetClusterv7ClusterInternalNetworks(ctx).Execute()
return networks, err
}

// ListClusterAcs get the cluster acs status.
func ListClusterAcs(ctx context.Context, client *client.Client) (*powerscale.V14ClusterAcs, error) {
acs, _, err := client.PscaleOpenAPIClient.ClusterApi.ListClusterv14ClusterAcs(ctx).Execute()
return acs, err
}
30 changes: 23 additions & 7 deletions powerscale/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ func CopyFields(ctx context.Context, source, destination interface{}) error {
// Get the type of the destination struct
//destinationType := destinationValue.Elem().Type()
for i := 0; i < sourceValue.NumField(); i++ {
sourceFieldName := sourceValue.Type().Field(i).Name
sourceFieldTag := getFieldJSONTag(sourceValue, i)

tflog.Debug(ctx, "Converting source field", map[string]interface{}{
"sourceFieldName": sourceFieldName,
"sourceFieldTag": sourceFieldTag,
"sourceFieldKind": sourceValue.Field(i).Kind().String(),
})

Expand All @@ -70,13 +70,13 @@ func CopyFields(ctx context.Context, source, destination interface{}) error {
}
if !sourceField.IsValid() {
tflog.Error(ctx, "source field is not valid", map[string]interface{}{
"sourceFieldName": sourceFieldName,
"sourceField": sourceField,
"sourceFieldTag": sourceFieldTag,
"sourceField": sourceField,
})
continue
}

destinationField := destinationValue.Elem().FieldByName(sourceFieldName)
destinationField := getFieldByTfTag(destinationValue.Elem(), sourceFieldTag)
if destinationField.IsValid() && destinationField.CanSet() {

tflog.Debug(ctx, "debugging source field", map[string]interface{}{
Expand Down Expand Up @@ -161,6 +161,22 @@ func CopyFields(ctx context.Context, source, destination interface{}) error {
return nil
}

func getFieldJSONTag(sourceValue reflect.Value, i int) string {
sourceFieldTag := sourceValue.Type().Field(i).Tag.Get("json")
sourceFieldTag = strings.TrimSuffix(sourceFieldTag, ",omitempty")
return sourceFieldTag
}

func getFieldByTfTag(destinationValue reflect.Value, tagValue string) reflect.Value {
for j := 0; j < destinationValue.NumField(); j++ {
field := destinationValue.Type().Field(j)
if field.Tag.Get("tfsdk") == tagValue {
return destinationValue.Field(j)
}
}
return reflect.Value{}
}

func copySliceToTargetField(ctx context.Context, fields interface{}) attr.Value {
var objects []attr.Value
attrTypeMap := make(map[string]attr.Type)
Expand Down Expand Up @@ -211,7 +227,7 @@ func copySliceToTargetField(ctx context.Context, fields interface{}) attr.Value
return nil
}

// ParseBody parses the error message from an openApi error response
// ParseBody parses the error message from an openApi error response.
func ParseBody(body []byte) (string, error) {
var parsedData map[string]string
err := json.Unmarshal(body, &parsedData)
Expand All @@ -225,7 +241,7 @@ func ParseBody(body []byte) (string, error) {
return message, nil
}

// GetErrorString extracts the error message from an openApi error response
// GetErrorString extracts the error message from an openApi error response.
func GetErrorString(err error, errStr string) string {
err1, ok := err.(*powerscale.GenericOpenAPIError)
message := ""
Expand Down
4 changes: 2 additions & 2 deletions powerscale/models/access_zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type AccessZoneDataSourceModel struct {
AccessZoneFilter *AccessZoneFilterType `tfsdk:"filter"`
}

// AccessZoneDetailModel details of the accessZone
// AccessZoneDetailModel details of the accessZone.
type AccessZoneDetailModel struct {
// Specifies an alternate system provider.
AlternateSystemProvider types.String `tfsdk:"alternate_system_provider"`
Expand Down Expand Up @@ -68,7 +68,7 @@ type AccessZoneDetailModel struct {
ZoneID types.Int64 `tfsdk:"zone_id"`
}

// V1AuthAccessAccessItemFileGroup IfsRestricted object
// V1AuthAccessAccessItemFileGroup IfsRestricted object.
type V1AuthAccessAccessItemFileGroup struct {
// Specifies the serialized form of a persona, which can be 'UID:0', 'USER:name', 'GID:0', 'GROUP:wheel', or 'SID:S-1-1'.
ID types.String `tfsdk:"id"`
Expand Down
25 changes: 21 additions & 4 deletions powerscale/models/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package models

import "github.com/hashicorp/terraform-plugin-framework/types"

// ClusterDataSource returns the overall cluster details
// ClusterDataSource returns the overall cluster details.
type ClusterDataSource struct {
ID types.String `tfsdk:"id"`
Config *ClusterConfig `tfsdk:"config"`
Identity *ClusterIdentity `tfsdk:"identity"`
Nodes *ClusterNodes `tfsdk:"nodes"`
InternalNetworks *ClusterInternalNetworks `tfsdk:"internal_networks"`
ACS *ClusterAcs `tfsdk:"acs"`
}

// ClusterConfig returns the configuration information of cluster.
Expand All @@ -25,7 +26,7 @@ type ClusterConfig struct {
Timezone *ClusterConfigTimezone `tfsdk:"timezone"`
}

// ClusterConfigOnefsVersion struct for ClusterConfigOnefsVersion
// ClusterConfigOnefsVersion struct for ClusterConfigOnefsVersion.
type ClusterConfigOnefsVersion struct {
// OneFS build string.
Build types.String `tfsdk:"build"`
Expand All @@ -51,7 +52,7 @@ type ClusterConfigTimezone struct {
Path types.String `tfsdk:"path"`
}

// ClusterConfigDevice refers to device information of a cluster
// ClusterConfigDevice refers to device information of a cluster.
type ClusterConfigDevice struct {
// Device ID.
DevID types.Int64 `tfsdk:"devid"`
Expand Down Expand Up @@ -83,7 +84,7 @@ type ClusterIdentityLogon struct {
MotdHeader types.String `tfsdk:"motd_header"`
}

// ClusterNodes struct for ClusterNodes
// ClusterNodes struct for ClusterNodes.
type ClusterNodes struct {
// A list of errors encountered by the individual nodes involved in this request, or an empty list if there were no errors.
Errors []NodeStatusError `tfsdk:"errors"`
Expand Down Expand Up @@ -542,3 +543,19 @@ type ClusterInternalNetworksFailoverIPAddresse struct {
// IPv4 address in the format: xxx.xxx.xxx.xxx
Low types.String `tfsdk:"low"`
}

// ClusterAcs Cluster ACS status.
type ClusterAcs struct {
// list of failed nodes serial number.
FailedNodesSn types.List `tfsdk:"failed_nodes_sn"`
// the number of joined nodes.
JoinedNodes types.Int64 `tfsdk:"joined_nodes"`
// the status of license activation.
LicenseStatus types.String `tfsdk:"license_status"`
// the status of SRS enablement.
SrsStatus types.String `tfsdk:"srs_status"`
// total nodes number of the cluster.
TotalNodes types.Int64 `tfsdk:"total_nodes"`
// list of unresponsive nodes serial number.
UnresponsiveSn types.List `tfsdk:"unresponsive_sn"`
}
2 changes: 1 addition & 1 deletion powerscale/provider/access_zone_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ func (r *AccessZoneResource) Read(ctx context.Context, req resource.ReadRequest,
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

// Update updates the resource state Path, Name, AuthProviders
// Update updates the resource state Path, Name, AuthProviders.
func (r *AccessZoneResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
tflog.Info(ctx, "updating access zone")
var plan *models.AccessZoneResourceModel
Expand Down
Loading

0 comments on commit 7aefdef

Please sign in to comment.