diff --git a/docs/data-sources/machine_pool.md b/docs/data-sources/machine_pool.md new file mode 100644 index 00000000..a2efbe16 --- /dev/null +++ b/docs/data-sources/machine_pool.md @@ -0,0 +1,57 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "rhcs_machine_pool Data Source - terraform-provider-rhcs" +subcategory: "" +description: |- + Machine pool. +--- + +# rhcs_machine_pool (Data Source) + +Machine pool. + +## Example Usage + +```terraform +data "rhcs_machine_pool" "machine_pool" { + cluster = var.cluster_id + id = var.machine_pool_id +} +``` + + +## Schema + +### Required + +- `cluster` (String) Identifier of the cluster of the machine pool. +- `id` (String) Unique identifier of the machine pool. + +### Read-Only + +- `autoscaling_enabled` (Boolean) Specifies whether auto-scaling is activated for this machine pool. +- `availability_zone` (String) A single availability zone in which the machines of this machine pool are created. Relevant only for a single availability zone machine pool. For multiple availability zones check "availability_zones" attribute +- `availability_zones` (List of String) A list of Availability Zones. Relevant only for multiple availability zones machine pool. For single availability zone check "availability_zone" attribute. +- `aws_additional_security_group_ids` (List of String) AWS additional security group ids. +- `disk_size` (Number) The root disk size, in GiB. +- `labels` (Map of String) The list of the Labels of this machine pool. +- `machine_type` (String) Identifier of the machine type used by the nodes, for example `m5.xlarge`. +- `max_replicas` (Number) The maximum number of replicas for auto-scaling functionality. relevant only in case of 'autoscaling_enabled = true' +- `max_spot_price` (Number) Max Spot price. +- `min_replicas` (Number) The minimum number of replicas for autos-caling functionality. relevant only in case of 'autoscaling_enabled = true +- `multi_availability_zone` (Boolean) Specifies whether this machine pool is a multi-AZ machine pool. Relevant only in case of multi-AZ cluster +- `name` (String) The name of the machine pool +- `replicas` (Number) The machines number in the machine pool. relevant only in case of 'autoscaling_enabled = false' +- `subnet_id` (String) An ID of single subnet in which the machines of this machine pool are created. Relevant only for a machine pool with single subnet. For machine pool with multiple subnets check "subnet_ids" attribute +- `subnet_ids` (List of String) A list of IDs of subnets in which the machines of this machine pool are created. Relevant only for a machine pool with multiple subnets. For machine pool with single subnet check "subnet_id" attribute +- `taints` (Attributes List) The list of the Taints of this machine pool. (see [below for nested schema](#nestedatt--taints)) +- `use_spot_instances` (Boolean) Indicates if Amazon EC2 Spot Instances used in this machine pool. + + +### Nested Schema for `taints` + +Read-Only: + +- `key` (String) Taints key +- `schedule_type` (String) Taints schedule type +- `value` (String) Taints value diff --git a/docs/resources/machine_pool.md b/docs/resources/machine_pool.md index e23dc633..709b7931 100644 --- a/docs/resources/machine_pool.md +++ b/docs/resources/machine_pool.md @@ -49,7 +49,9 @@ resource "rhcs_machine_pool" "machine_pool" { ### Read-Only +- `availability_zones` (List of String) A list of Availability Zones. Relevant only for multiple availability zones machine pool. For single availability zone check "availability_zone" attribute. - `id` (String) Unique identifier of the machine pool. +- `subnet_ids` (List of String) A list of IDs of subnets in which the machines of this machine pool are created. Relevant only for a machine pool with multiple subnets. For machine pool with single subnet check "subnet_id" attribute ### Nested Schema for `taints` diff --git a/generate_example_usages/data-sources/rhcs_machine_pool/data-source.tf b/generate_example_usages/data-sources/rhcs_machine_pool/data-source.tf new file mode 100644 index 00000000..4490c321 --- /dev/null +++ b/generate_example_usages/data-sources/rhcs_machine_pool/data-source.tf @@ -0,0 +1,4 @@ +data "rhcs_machine_pool" "machine_pool" { + cluster = var.cluster_id + id = var.machine_pool_id +} diff --git a/provider/machinepool/machine_pool_datasource.go b/provider/machinepool/machine_pool_datasource.go new file mode 100644 index 00000000..06d975c2 --- /dev/null +++ b/provider/machinepool/machine_pool_datasource.go @@ -0,0 +1,191 @@ +/* +Copyright (c) 2021 Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package machinepool + +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" + sdk "github.com/openshift-online/ocm-sdk-go" + cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" +) + +type MachinePoolDatasource struct { + collection *cmv1.ClustersClient +} + +var _ datasource.DataSource = &MachinePoolDatasource{} +var _ datasource.DataSourceWithConfigure = &MachinePoolDatasource{} + +func NewDatasource() datasource.DataSource { + return &MachinePoolDatasource{} +} + +func (r *MachinePoolDatasource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_machine_pool" +} + +func (r *MachinePoolDatasource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + connection, ok := req.ProviderData.(*sdk.Connection) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *sdk.Connaction, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + r.collection = connection.ClustersMgmt().V1().Clusters() +} + +func (r *MachinePoolDatasource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Machine pool.", + Attributes: map[string]schema.Attribute{ + "cluster": schema.StringAttribute{ + Description: "Identifier of the cluster of the machine pool. ", + Required: true, + }, + "id": schema.StringAttribute{ + Description: "Unique identifier of the machine pool.", + Required: true, + }, + "name": schema.StringAttribute{ + Description: "The name of the machine pool", + Computed: true, + }, + "machine_type": schema.StringAttribute{ + Description: "Identifier of the machine type used by the nodes, for example `m5.xlarge`. ", + Computed: true, + }, + "replicas": schema.Int64Attribute{ + Description: "The machines number in the machine pool. relevant only in case of 'autoscaling_enabled = false'", + Computed: true, + }, + "use_spot_instances": schema.BoolAttribute{ + Description: "Indicates if Amazon EC2 Spot Instances used in this machine pool.", + Computed: true, + }, + "max_spot_price": schema.Float64Attribute{ + Description: "Max Spot price.", + Computed: true, + }, + "autoscaling_enabled": schema.BoolAttribute{ + Description: "Specifies whether auto-scaling is activated for this machine pool.", + Computed: true, + }, + "min_replicas": schema.Int64Attribute{ + Description: "The minimum number of replicas for autos-caling functionality. relevant only in case of 'autoscaling_enabled = true", + Computed: true, + }, + "max_replicas": schema.Int64Attribute{ + Description: "The maximum number of replicas for auto-scaling functionality. relevant only in case of 'autoscaling_enabled = true'", + Computed: true, + }, + "taints": schema.ListNestedAttribute{ + Description: "The list of the Taints of this machine pool.", + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "key": schema.StringAttribute{ + Description: "Taints key", + Computed: true, + }, + "value": schema.StringAttribute{ + Description: "Taints value", + Computed: true, + }, + "schedule_type": schema.StringAttribute{ + Description: "Taints schedule type", + Computed: true, + }, + }, + }, + Computed: true, + }, + "labels": schema.MapAttribute{ + Description: "The list of the Labels of this machine pool.", + ElementType: types.StringType, + Computed: true, + }, + "multi_availability_zone": schema.BoolAttribute{ + Description: "Specifies whether this machine pool is a multi-AZ machine pool. Relevant only in case of multi-AZ cluster", + Computed: true, + }, + "availability_zone": schema.StringAttribute{ + Description: "A single availability zone in which the machines of this machine pool are created. Relevant only for a single availability zone machine pool. For multiple availability zones check \"availability_zones\" attribute", + Computed: true, + }, + "availability_zones": schema.ListAttribute{ + Description: "A list of Availability Zones. Relevant only for multiple availability zones machine pool. For single availability zone check \"availability_zone\" attribute.", + ElementType: types.StringType, + Computed: true, + }, + "subnet_id": schema.StringAttribute{ + Description: "An ID of single subnet in which the machines of this machine pool are created. Relevant only for a machine pool with single subnet. For machine pool with multiple subnets check \"subnet_ids\" attribute", + Computed: true, + }, + "subnet_ids": schema.ListAttribute{ + Description: "A list of IDs of subnets in which the machines of this machine pool are created. Relevant only for a machine pool with multiple subnets. For machine pool with single subnet check \"subnet_id\" attribute", + ElementType: types.StringType, + Computed: true, + }, + "disk_size": schema.Int64Attribute{ + Description: "The root disk size, in GiB.", + Computed: true, + }, + "aws_additional_security_group_ids": schema.ListAttribute{ + Description: "AWS additional security group ids.", + ElementType: types.StringType, + Computed: true, + }, + }, + } +} + +func (r *MachinePoolDatasource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + // Get the current state: + state := &MachinePoolState{} + diags := req.Config.Get(ctx, state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + notFound, diags := readState(ctx, state, r.collection) + if notFound { + diags.AddError( + "Failed to find machine pool", + fmt.Sprintf( + "Failed to find machine pool with identifier %s for cluster %s.", + state.ID.ValueString(), state.Cluster.ValueString(), + ), + ) + return + } + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, state)...) +} diff --git a/provider/machinepool/machine_pool_resource.go b/provider/machinepool/machine_pool_resource.go index 7981279c..224a67e2 100644 --- a/provider/machinepool/machine_pool_resource.go +++ b/provider/machinepool/machine_pool_resource.go @@ -176,6 +176,11 @@ func (r *MachinePoolResource) Schema(ctx context.Context, req resource.SchemaReq stringplanmodifier.UseStateForUnknown(), }, }, + "availability_zones": schema.ListAttribute{ + Description: "A list of Availability Zones. Relevant only for multiple availability zones machine pool. For single availability zone check \"availability_zone\" attribute.", + ElementType: types.StringType, + Computed: true, + }, "subnet_id": schema.StringAttribute{ Description: "Select the subnet in which to create a single AZ machine pool for BYO-VPC cluster. " + common.ValueCannotBeChangedStringDescription, Optional: true, @@ -184,6 +189,11 @@ func (r *MachinePoolResource) Schema(ctx context.Context, req resource.SchemaReq stringplanmodifier.UseStateForUnknown(), }, }, + "subnet_ids": schema.ListAttribute{ + Description: "A list of IDs of subnets in which the machines of this machine pool are created. Relevant only for a machine pool with multiple subnets. For machine pool with single subnet check \"subnet_id\" attribute", + ElementType: types.StringType, + Computed: true, + }, "disk_size": schema.Int64Attribute{ Description: "Root disk size, in GiB. " + common.ValueCannotBeChangedStringDescription, Optional: true, @@ -413,7 +423,7 @@ func (r *MachinePoolResource) Create(ctx context.Context, req resource.CreateReq object = add.Body() // Save the state: - err = r.populateState(object, plan) + err = populateState(object, plan) if err != nil { resp.Diagnostics.AddError( "Can't populate machine pool state", @@ -439,7 +449,7 @@ func (r *MachinePoolResource) magicImport(ctx context.Context, plan *MachinePool } plan.ID = types.StringValue(machinepoolName) - notFound, diags := r.readState(ctx, state) + notFound, diags := readState(ctx, state, r.collection) if notFound { // We disallow creating a machine pool with the default name. This // case can only happen if the default machine pool was deleted and @@ -477,7 +487,7 @@ func (r *MachinePoolResource) Read(ctx context.Context, req resource.ReadRequest return } - notFound, diags := r.readState(ctx, state) + notFound, diags := readState(ctx, state, r.collection) if notFound { // If we can't find the machine pool, it was deleted. Remove if from the // state and don't return an error so the TF apply() will automatically @@ -496,10 +506,10 @@ func (r *MachinePoolResource) Read(ctx context.Context, req resource.ReadRequest resp.Diagnostics.Append(resp.State.Set(ctx, state)...) } -func (r *MachinePoolResource) readState(ctx context.Context, state *MachinePoolState) (poolNotFound bool, diags diag.Diagnostics) { +func readState(ctx context.Context, state *MachinePoolState, collection *cmv1.ClustersClient) (poolNotFound bool, diags diag.Diagnostics) { diags = diag.Diagnostics{} - resource := r.collection.Cluster(state.Cluster.ValueString()). + resource := collection.Cluster(state.Cluster.ValueString()). MachinePools(). MachinePool(state.ID.ValueString()) get, err := resource.Get().SendContext(ctx) @@ -518,7 +528,7 @@ func (r *MachinePoolResource) readState(ctx context.Context, state *MachinePoolS } object := get.Body() - err = r.populateState(object, state) + err = populateState(object, state) if err != nil { diags.AddError( "Can't populate machine pool state", @@ -706,7 +716,7 @@ func (r *MachinePoolResource) doUpdate(ctx context.Context, state *MachinePoolSt state.Replicas = plan.Replicas // Save the state: - err = r.populateState(object, state) + err = populateState(object, state) if err != nil { diags.AddError( "Can't populate machine pool state", @@ -903,7 +913,7 @@ func (r *MachinePoolResource) ImportState(ctx context.Context, req resource.Impo } // populateState copies the data from the API object to the Terraform state. -func (r *MachinePoolResource) populateState(object *cmv1.MachinePool, state *MachinePoolState) error { +func populateState(object *cmv1.MachinePool, state *MachinePoolState) error { state.ID = types.StringValue(object.ID()) state.Name = types.StringValue(object.ID()) @@ -986,16 +996,28 @@ func (r *MachinePoolResource) populateState(object *cmv1.MachinePool, state *Mac if len(azs) == 1 { state.AvailabilityZone = types.StringValue(azs[0]) state.MultiAvailabilityZone = types.BoolValue(false) + state.AvailabilityZones = types.ListNull(types.StringType) } else { state.AvailabilityZone = types.StringValue("") + azListValue, err := common.StringArrayToList(azs) + if err != nil { + return err + } + state.AvailabilityZones = azListValue } subnets := object.Subnets() if len(subnets) == 1 { state.SubnetID = types.StringValue(subnets[0]) state.MultiAvailabilityZone = types.BoolValue(false) + state.SubnetIDs = types.ListNull(types.StringType) } else { state.SubnetID = types.StringValue("") + subnetListValue, err := common.StringArrayToList(subnets) + if err != nil { + return err + } + state.SubnetIDs = subnetListValue } state.DiskSize = types.Int64Null() diff --git a/provider/machinepool/machine_pool_state.go b/provider/machinepool/machine_pool_state.go index 0ad28484..8309a1ff 100644 --- a/provider/machinepool/machine_pool_state.go +++ b/provider/machinepool/machine_pool_state.go @@ -35,7 +35,9 @@ type MachinePoolState struct { Labels types.Map `tfsdk:"labels"` MultiAvailabilityZone types.Bool `tfsdk:"multi_availability_zone"` AvailabilityZone types.String `tfsdk:"availability_zone"` + AvailabilityZones types.List `tfsdk:"availability_zones"` SubnetID types.String `tfsdk:"subnet_id"` + SubnetIDs types.List `tfsdk:"subnet_ids"` DiskSize types.Int64 `tfsdk:"disk_size"` AdditionalSecurityGroupIds types.List `tfsdk:"aws_additional_security_group_ids"` } diff --git a/provider/provider.go b/provider/provider.go index f9aa63a3..29f3ee1a 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -225,5 +225,6 @@ func (p *Provider) DataSources(ctx context.Context) []func() datasource.DataSour versions.New, info.New, clusterrosaclassic.NewDataSource, + machinepool.NewDatasource, } }