diff --git a/internal/service/eks/cluster_versions_data_source.go b/internal/service/eks/cluster_versions_data_source.go new file mode 100644 index 000000000000..26b0b8c901d3 --- /dev/null +++ b/internal/service/eks/cluster_versions_data_source.go @@ -0,0 +1,163 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package eks + +import ( + "context" + "fmt" + + "github.com/aws/aws-sdk-go-v2/service/eks" + awstypes "github.com/aws/aws-sdk-go-v2/service/eks/types" + "github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkDataSource("aws_eks_cluster_versions", name="Cluster Versions") +func newDataSourceClusterVersions(context.Context) (datasource.DataSourceWithConfigure, error) { + return &dataSourceClusterVersions{}, nil +} + +const ( + DSNameClusterVersions = "Cluster Versions Data Source" +) + +type dataSourceClusterVersions struct { + framework.DataSourceWithConfigure +} + +func (d *dataSourceClusterVersions) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name + resp.TypeName = "aws_eks_cluster_versions" +} + +func (d *dataSourceClusterVersions) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "cluster_type": schema.StringAttribute{ + Optional: true, + }, + "cluster_versions_only": schema.ListAttribute{ + Optional: true, + CustomType: fwtypes.ListOfStringType, + }, + "default_only": schema.BoolAttribute{ + Optional: true, + }, + "include_all": schema.BoolAttribute{ + Optional: true, + }, + names.AttrStatus: schema.StringAttribute{ + Optional: true, + CustomType: fwtypes.StringEnumType[clusterVersionAWSStatus](), + }, + "cluster_versions": framework.DataSourceComputedListOfObjectAttribute[customDataSourceClusterVersion](ctx), + }, + } +} + +func (d *dataSourceClusterVersions) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + conn := d.Meta().EKSClient(ctx) + + var data dataSourceClusterVersionsModel + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + input := &eks.DescribeClusterVersionsInput{} + + if data.ClusterType.String() != "" { + input.ClusterType = data.ClusterType.ValueStringPointer() + } + + input.DefaultOnly = data.DefaultOnly.ValueBoolPointer() + + if len(data.ClusterVersionsOnly.Elements()) > 0 && !data.ClusterVersions.IsNull() { + clVersions := make([]string, 0, len(data.ClusterVersionsOnly.Elements())) + for _, v := range data.ClusterVersionsOnly.Elements() { + clVersions = append(clVersions, v.String()) + } + + input.ClusterVersions = clVersions + } + + if data.Status.String() != "" { + input.Status = awstypes.ClusterVersionStatus(data.Status.ValueString()) + } + + // TIP: -- 3. Get information about a resource from AWS + out, err := findClusterVersions(ctx, conn, input) + if err != nil { + resp.Diagnostics.AddError(fmt.Sprint(names.EKS, create.ErrActionReading, DSNameClusterVersions, err), err.Error()) + return + } + + output := &eks.DescribeClusterVersionsOutput{ + ClusterVersions: out, + } + + resp.Diagnostics.Append(flex.Flatten(ctx, output, &data)...) + if resp.Diagnostics.HasError() { + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func findClusterVersions(ctx context.Context, conn *eks.Client, input *eks.DescribeClusterVersionsInput) ([]awstypes.ClusterVersionInformation, error) { + output := make([]awstypes.ClusterVersionInformation, 0) + + pages := eks.NewDescribeClusterVersionsPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + if err != nil { + return nil, err + } + + output = append(output, page.ClusterVersions...) + } + + return output, nil +} + +type clusterVersionAWSStatus string + +// Values returns all known values for ClusterVersionStatus. Note that this can be +// expanded in the future, and so it is only as up to date as the client. +// +// The ordering of this slice is not guaranteed to be stable across updates. +func (clusterVersionAWSStatus) Values() []clusterVersionAWSStatus { + return []clusterVersionAWSStatus{ + "UNSUPPORTED", + "STANDARD_SUPPORT", + "EXTENDED_SUPPORT", + } +} + +type dataSourceClusterVersionsModel struct { + ClusterType types.String `tfsdk:"cluster_type"` + DefaultOnly types.Bool `tfsdk:"default_only"` + IncludeAll types.Bool `tfsdk:"include_all"` + ClusterVersionsOnly fwtypes.ListValueOf[types.String] `tfsdk:"cluster_versions_only"` + Status fwtypes.StringEnum[clusterVersionAWSStatus] `tfsdk:"status"` + ClusterVersions fwtypes.ListNestedObjectValueOf[customDataSourceClusterVersion] `tfsdk:"cluster_versions"` +} + +type customDataSourceClusterVersion struct { + ClusterType types.String `tfsdk:"cluster_type"` + ClusterVersion types.String `tfsdk:"cluster_version"` + DefaultPlatformVersion types.String `tfsdk:"default_platform_version"` + EndOfExtendedSupportDate timetypes.RFC3339 `tfsdk:"end_of_extended_support_date"` + EndOfStandardSupportDate timetypes.RFC3339 `tfsdk:"end_of_standard_support_date"` + KubernetesPatchVersion types.String `tfsdk:"kubernetes_patch_version"` + ReleaseDate timetypes.RFC3339 `tfsdk:"release_date"` + DefaultVersion types.Bool `tfsdk:"default_version"` + Status fwtypes.StringEnum[clusterVersionAWSStatus] `tfsdk:"status"` +} diff --git a/internal/service/eks/cluster_versions_data_source_test.go b/internal/service/eks/cluster_versions_data_source_test.go new file mode 100644 index 000000000000..62f9df3e6aec --- /dev/null +++ b/internal/service/eks/cluster_versions_data_source_test.go @@ -0,0 +1,126 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package eks_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccEKSClusterVersionsDataSource_basic(t *testing.T) { + ctx := acctest.Context(t) + + dataSourceName := "data.aws_eks_cluster_versions.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EKSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccClusterVersionsDataSourceConfig_basic(), + Check: resource.ComposeAggregateTestCheckFunc( + acctest.CheckResourceAttrGreaterThanValue(dataSourceName, "cluster_versions.#", 0), + acctest.CheckResourceAttrContains(dataSourceName, "cluster_versions.0.default_version", acctest.CtTrue), + ), + }, + }, + }) +} + +func TestAccEKSClusterVersionsDataSource_clusterType(t *testing.T) { + ctx := acctest.Context(t) + + dataSourceName := "data.aws_eks_cluster_versions.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EKSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccClusterVersionsDataSourceConfig_clusterType(), + Check: resource.ComposeTestCheckFunc( + acctest.CheckResourceAttrGreaterThanValue(dataSourceName, "cluster_versions.#", 0), + ), + }, + }, + }) +} + +func TestAccEKSClusterVersionsDataSource_defaultOnly(t *testing.T) { + ctx := acctest.Context(t) + + dataSourceName := "data.aws_eks_cluster_versions.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EKSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccClusterVersionsDataSourceConfig_defaultOnly(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "cluster_versions.#", "1"), + acctest.CheckResourceAttrContains(dataSourceName, "cluster_versions.0.default_version", acctest.CtTrue), + ), + }, + }, + }) +} + +func TestAccEKSClusterVersionsDataSource_status(t *testing.T) { + ctx := acctest.Context(t) + + dataSourceName := "data.aws_eks_cluster_versions.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.EKSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccClusterVersionsDataSourceConfig_status(), + Check: resource.ComposeTestCheckFunc( + acctest.CheckResourceAttrGreaterThanValue(dataSourceName, "cluster_versions.#", 0), + acctest.CheckResourceAttrContains(dataSourceName, "cluster_versions.0.status", "STANDARD_SUPPORT"), + ), + }, + }, + }) +} + +func testAccClusterVersionsDataSourceConfig_basic() string { + return acctest.ConfigCompose(` +data "aws_eks_cluster_versions" "test" { +} +`) +} + +func testAccClusterVersionsDataSourceConfig_clusterType() string { + return acctest.ConfigCompose(` +data "aws_eks_cluster_versions" "test" { + cluster_type = "eks" +} +`) +} + +func testAccClusterVersionsDataSourceConfig_defaultOnly() string { + return acctest.ConfigCompose(` +data "aws_eks_cluster_versions" "test" { + default_only = true +} +`) +} + +func testAccClusterVersionsDataSourceConfig_status() string { + return acctest.ConfigCompose(` +data "aws_eks_cluster_versions" "test" { + status = "STANDARD_SUPPORT" +} +`) +} diff --git a/internal/service/eks/service_package_gen.go b/internal/service/eks/service_package_gen.go index 3d56499938d8..efe2e4ecec70 100644 --- a/internal/service/eks/service_package_gen.go +++ b/internal/service/eks/service_package_gen.go @@ -25,7 +25,13 @@ func (p *servicePackage) EphemeralResources(ctx context.Context) []*types.Servic } func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.ServicePackageFrameworkDataSource { - return []*types.ServicePackageFrameworkDataSource{} + return []*types.ServicePackageFrameworkDataSource{ + { + Factory: newDataSourceClusterVersions, + TypeName: "aws_eks_cluster_versions", + Name: "Cluster Versions", + }, + } } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { diff --git a/website/docs/d/eks_cluster_versions.html.markdown b/website/docs/d/eks_cluster_versions.html.markdown new file mode 100644 index 000000000000..d38d7fb42694 --- /dev/null +++ b/website/docs/d/eks_cluster_versions.html.markdown @@ -0,0 +1,47 @@ +--- +subcategory: "EKS (Elastic Kubernetes)" +layout: "aws" +page_title: "AWS: aws_eks_cluster_versions" +description: |- + Terraform data source for managing an AWS EKS (Elastic Kubernetes) Cluster Versions. +--- + +# Data Source: aws_eks_cluster_versions + +Terraform data source for managing an AWS EKS (Elastic Kubernetes) Cluster Versions. + +## Example Usage + +### Basic Usage + +```terraform +data "aws_eks_cluster_versions" "example" {} + +data "aws_eks_cluster_versions" "example" { + cluster_type = "eks" +} +``` + +## Argument Reference + +The following arguments are optional: + +* `cluster_type` - (Optional) The type of clusters to filter by. Currently only `eks` is supported. +* `default_only` - (Optional) Whether to show only the default versions of Kubernetes supported by EKS. Default is `false`. +* `cluster_versions` - (Optional) A list of Kubernetes versions that you can use to check if EKS supports it. +* `include_all` - (Optional) Whether to include all kubernetes versions in the response. Default is `false`. +* `status` - (Optional) The status of the EKS cluster versions to list. Can be `STANDARD_SUPPORT` or `UNSUPPORTED` or `EXTENDED_SUPPORT`. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `cluster_version` - The Kubernetes version supported by EKS. +* `cluster_type` - The type of cluster that the version belongs to. Currently only `eks` is supported. +* `default_platform_version` - The default eks platform version for the cluster version. +* `default_version` - The default Kubernetes version for the cluster version. +* `status` - The status of the EKS cluster version. Can be `STANDARD_SUPPORT` or `UNSUPPORTED` or `EXTENDED_SUPPORT`. +* `end_of_extended_support_date` - The end of extended support date for the cluster version. +* `end_of_standard_support_date` - The end of standard support date for the cluster version. +* `kubernetes_patch_version` - The Kubernetes patch version for the cluster version. +* `release_date` - The release date of the cluster version.