diff --git a/.changelog/29741.txt b/.changelog/29741.txt new file mode 100644 index 00000000000..7e7cea0e465 --- /dev/null +++ b/.changelog/29741.txt @@ -0,0 +1,19 @@ +```release-note:new-resource +aws_licensemanager_grant +``` + +```release-note:new-resource +aws_licensemanager_grant_accepter +``` + +```release-note:new-data-source +aws_licensemanager_received_license +``` + +```release-note:new-data-source +aws_licensemanager_received_licenses +``` + +```release-note:new-data-source +aws_licensemanager_grants +``` \ No newline at end of file diff --git a/.teamcity/components/generated/service_orgacct.kt b/.teamcity/components/generated/service_orgacct.kt index 339ae3c64d6..76b95980d05 100644 --- a/.teamcity/components/generated/service_orgacct.kt +++ b/.teamcity/components/generated/service_orgacct.kt @@ -9,6 +9,7 @@ val orgacctServices = mapOf( "config" to ServiceSpec("Config" /*"TestAccConfig_serial|TestAccConfigConfigurationAggregator_"*/), "fms" to ServiceSpec("FMS"), "guardduty" to ServiceSpec("GuardDuty"), + "licensemanager" to ServiceSpec("License Manager"), "macie2" to ServiceSpec("Macie2"), "organizations" to ServiceSpec("Organizations"), "securityhub" to ServiceSpec( diff --git a/docs/acc-test-environment-variables.md b/docs/acc-test-environment-variables.md index 64392327c6a..a3d5df02a9c 100644 --- a/docs/acc-test-environment-variables.md +++ b/docs/acc-test-environment-variables.md @@ -83,4 +83,7 @@ Environment variables (beyond standard AWS Go SDK ones) used by acceptance testi | `TEST_AWS_SES_VERIFIED_EMAIL_ARN` | Verified SES Email Identity for use in Cognito User Pool testing. | | `TF_ACC` | Enables Go tests containing `resource.Test()` and `resource.ParallelTest()`. | | `TF_ACC_ASSUME_ROLE_ARN` | Amazon Resource Name of existing IAM Role to use for limited permissions acceptance testing. | +| `TF_AWS_LICENSE_MANAGER_GRANT_HOME_REGION` | Region where a License Manager license is imported. | +| `TF_AWS_LICENSE_MANAGER_GRANT_LICENSE_ARN` | ARN for a License Manager license imported into the current account. | +| `TF_AWS_LICENSE_MANAGER_GRANT_PRINCIPAL` | ARN of a principal to share the License Manager license with. Either a root user, Organization, or Organizational Unit. | | `TF_TEST_CLOUDFRONT_RETAIN` | Flag to disable but dangle CloudFront Distributions during testing to reduce feedback time (must be manually destroyed afterwards) | diff --git a/internal/acctest/acctest.go b/internal/acctest/acctest.go index be342bd4a76..162144d1ebb 100644 --- a/internal/acctest/acctest.go +++ b/internal/acctest/acctest.go @@ -126,6 +126,26 @@ func protoV5ProviderFactoriesInit(ctx context.Context, providerNames ...string) return factories } +func protoV5ProviderFactoriesNamedInit(ctx context.Context, t *testing.T, providers map[string]*schema.Provider, providerNames ...string) map[string]func() (tfprotov5.ProviderServer, error) { + factories := make(map[string]func() (tfprotov5.ProviderServer, error), len(providerNames)) + + for _, name := range providerNames { + providerServerFactory, p, err := provider.ProtoV5ProviderServerFactory(ctx) + + if err != nil { + t.Fatal(err) + } + + factories[name] = func() (tfprotov5.ProviderServer, error) { //nolint:unparam + return providerServerFactory(), nil + } + + providers[name] = p + } + + return factories +} + func protoV5ProviderFactoriesPlusProvidersInit(ctx context.Context, t *testing.T, providers *[]*schema.Provider, providerNames ...string) map[string]func() (tfprotov5.ProviderServer, error) { factories := make(map[string]func() (tfprotov5.ProviderServer, error), len(providerNames)) @@ -158,6 +178,10 @@ func ProtoV5FactoriesPlusProvidersAlternate(ctx context.Context, t *testing.T, p return protoV5ProviderFactoriesPlusProvidersInit(ctx, t, providers, ProviderName, ProviderNameAlternate) } +func ProtoV5FactoriesNamed(ctx context.Context, t *testing.T, providers map[string]*schema.Provider) map[string]func() (tfprotov5.ProviderServer, error) { + return protoV5ProviderFactoriesNamedInit(ctx, t, providers, ProviderName, ProviderNameAlternate) +} + func ProtoV5FactoriesAlternate(ctx context.Context, t *testing.T) map[string]func() (tfprotov5.ProviderServer, error) { return protoV5ProviderFactoriesInit(ctx, ProviderName, ProviderNameAlternate) } @@ -1172,6 +1196,26 @@ func RegionProviderFunc(region string, providers *[]*schema.Provider) func() *sc } } +func NamedProviderFunc(name string, providers map[string]*schema.Provider) func() *schema.Provider { + return func() *schema.Provider { + return NamedProvider(name, providers) + } +} + +func NamedProvider(name string, providers map[string]*schema.Provider) *schema.Provider { + if name == "" { + log.Printf("[ERROR] No name passed") + } + + p, ok := providers[name] + if !ok { + log.Printf("[ERROR] No provider named %q found", name) + return nil + } + + return p +} + func DeleteResource(ctx context.Context, resource *schema.Resource, d *schema.ResourceData, meta interface{}) error { if resource.DeleteContext != nil || resource.DeleteWithoutTimeout != nil { var diags diag.Diagnostics @@ -1228,6 +1272,23 @@ func CheckWithProviders(f TestCheckWithProviderFunc, providers *[]*schema.Provid } } +func CheckWithNamedProviders(f TestCheckWithProviderFunc, providers map[string]*schema.Provider) resource.TestCheckFunc { + return func(s *terraform.State) error { + numberOfProviders := len(providers) + for k, provo := range providers { + if provo.Meta() == nil { + log.Printf("[DEBUG] Skipping empty provider %q (total: %d)", k, numberOfProviders) + continue + } + log.Printf("[DEBUG] Calling check with provider %q (total: %d)", k, numberOfProviders) + if err := f(s, provo); err != nil { + return err + } + } + return nil + } +} + // ErrorCheckSkipMessagesContaining skips tests based on error messages that indicate unsupported features func ErrorCheckSkipMessagesContaining(t *testing.T, messages ...string) resource.ErrorCheckFunc { return func(err error) error { diff --git a/internal/service/licensemanager/association_test.go b/internal/service/licensemanager/association_test.go index cb44c6050dd..ddb80039dc4 100644 --- a/internal/service/licensemanager/association_test.go +++ b/internal/service/licensemanager/association_test.go @@ -28,7 +28,7 @@ func TestAccLicenseManagerAssociation_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAssociationConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAssociationExists(ctx, resourceName), resource.TestCheckResourceAttrPair(resourceName, "license_configuration_arn", "aws_licensemanager_license_configuration.test", "id"), resource.TestCheckResourceAttrPair(resourceName, "resource_arn", "aws_instance.test", "arn"), @@ -56,7 +56,7 @@ func TestAccLicenseManagerAssociation_disappears(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAssociationConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAssociationExists(ctx, resourceName), acctest.CheckResourceDisappears(ctx, acctest.Provider, tflicensemanager.ResourceAssociation(), resourceName), ), diff --git a/internal/service/licensemanager/common_schema_data_source.go b/internal/service/licensemanager/common_schema_data_source.go new file mode 100644 index 00000000000..db66c9cc0a8 --- /dev/null +++ b/internal/service/licensemanager/common_schema_data_source.go @@ -0,0 +1,45 @@ +package licensemanager + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/licensemanager" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func BuildFiltersDataSource(set *schema.Set) []*licensemanager.Filter { + var filters []*licensemanager.Filter + for _, v := range set.List() { + m := v.(map[string]interface{}) + var filterValues []*string + for _, e := range m["values"].([]interface{}) { + filterValues = append(filterValues, aws.String(e.(string))) + } + filters = append(filters, &licensemanager.Filter{ + Name: aws.String(m["name"].(string)), + Values: filterValues, + }) + } + return filters +} + +func DataSourceFiltersSchema() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "values": { + Type: schema.TypeList, + Required: true, + MinItems: 1, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + } +} diff --git a/internal/service/licensemanager/generate.go b/internal/service/licensemanager/generate.go index 7f0420d44ee..6f6c816647f 100644 --- a/internal/service/licensemanager/generate.go +++ b/internal/service/licensemanager/generate.go @@ -1,5 +1,5 @@ //go:generate go run ../../generate/tags/main.go -ServiceTagsSlice -UpdateTags -ContextOnly -//go:generate go run ../../generate/listpages/main.go -ListOps=ListLicenseConfigurations,ListLicenseSpecificationsForResource -ContextOnly +//go:generate go run ../../generate/listpages/main.go -ListOps=ListLicenseConfigurations,ListLicenseSpecificationsForResource,ListReceivedLicenses,ListDistributedGrants -ContextOnly // ONLY generate directives and package declaration! Do not add anything else to this file. package licensemanager diff --git a/internal/service/licensemanager/grant.go b/internal/service/licensemanager/grant.go new file mode 100644 index 00000000000..deb65ae42e7 --- /dev/null +++ b/internal/service/licensemanager/grant.go @@ -0,0 +1,237 @@ +package licensemanager + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/licensemanager" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" + "github.com/hashicorp/terraform-provider-aws/names" +) + +const ( + ResGrant = "Grant" +) + +// @SDKResource("aws_licensemanager_grant") +func ResourceGrant() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceGrantCreate, + ReadWithoutTimeout: resourceGrantRead, + UpdateWithoutTimeout: resourceGrantUpdate, + DeleteWithoutTimeout: resourceGrantDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "allowed_operations": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + MaxItems: len(licensemanager.AllowedOperation_Values()), + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice(licensemanager.AllowedOperation_Values(), true), + }, + Description: "Allowed operations for the grant. This is a subset of the allowed operations on the license.", + }, + "arn": { + Type: schema.TypeString, + Computed: true, + Description: "Amazon Resource Name (ARN) of the grant.", + }, + "home_region": { + Type: schema.TypeString, + Computed: true, + Description: "Home Region of the grant.", + }, + "license_arn": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidARN, + Description: "License ARN.", + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: "Name of the grant.", + }, + "parent_arn": { + Type: schema.TypeString, + Computed: true, + Description: "Parent ARN.", + }, + "principal": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidARN, + Description: "The grantee principal ARN. The target account for the grant in the form of the ARN for an account principal of the root user.", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "Grant status.", + }, + "version": { + Type: schema.TypeString, + Computed: true, + Description: "Grant version.", + }, + }, + } +} + +func resourceGrantCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + in := &licensemanager.CreateGrantInput{ + AllowedOperations: aws.StringSlice(expandAllowedOperations(d.Get("allowed_operations").(*schema.Set).List())), + ClientToken: aws.String(resource.UniqueId()), + GrantName: aws.String(d.Get("name").(string)), + HomeRegion: aws.String(meta.(*conns.AWSClient).Region), + LicenseArn: aws.String(d.Get("license_arn").(string)), + Principals: aws.StringSlice([]string{d.Get("principal").(string)}), + } + + out, err := conn.CreateGrantWithContext(ctx, in) + + if err != nil { + return create.DiagError(names.LicenseManager, create.ErrActionCreating, ResGrant, d.Get("name").(string), err) + } + + d.SetId(aws.StringValue(out.GrantArn)) + + return resourceGrantRead(ctx, d, meta) +} + +func resourceGrantRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + out, err := FindGrantByARN(ctx, conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + create.LogNotFoundRemoveState(names.LicenseManager, create.ErrActionReading, ResGrant, d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return create.DiagError(names.LicenseManager, create.ErrActionReading, ResGrant, d.Id(), err) + } + + d.Set("allowed_operations", out.GrantedOperations) + d.Set("arn", out.GrantArn) + d.Set("home_region", out.HomeRegion) + d.Set("license_arn", out.LicenseArn) + d.Set("name", out.GrantName) + d.Set("parent_arn", out.ParentArn) + d.Set("principal", out.GranteePrincipalArn) + d.Set("status", out.GrantStatus) + d.Set("version", out.Version) + + return nil +} + +func resourceGrantUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + in := &licensemanager.CreateGrantVersionInput{ + GrantArn: aws.String(d.Id()), + ClientToken: aws.String(resource.UniqueId()), + } + + if d.HasChange("allowed_operations") { + in.AllowedOperations = aws.StringSlice(d.Get("allowed_operations").([]string)) + } + + if d.HasChange("name") { + in.GrantName = aws.String(d.Get("name").(string)) + } + + _, err := conn.CreateGrantVersionWithContext(ctx, in) + + if err != nil { + return create.DiagError(names.LicenseManager, create.ErrActionUpdating, ResGrant, d.Id(), err) + } + + return resourceGrantRead(ctx, d, meta) +} + +func resourceGrantDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + out, err := FindGrantByARN(ctx, conn, d.Id()) + + if tfresource.NotFound(err) { + create.LogNotFoundRemoveState(names.LicenseManager, create.ErrActionReading, ResGrant, d.Id()) + return nil + } + + if err != nil { + return create.DiagError(names.LicenseManager, create.ErrActionReading, ResGrant, d.Id(), err) + } + + in := &licensemanager.DeleteGrantInput{ + GrantArn: aws.String(d.Id()), + Version: out.Version, + } + + _, err = conn.DeleteGrantWithContext(ctx, in) + + if err != nil { + return create.DiagError(names.LicenseManager, create.ErrActionDeleting, ResGrant, d.Id(), err) + } + + return nil +} + +func FindGrantByARN(ctx context.Context, conn *licensemanager.LicenseManager, arn string) (*licensemanager.Grant, error) { + in := &licensemanager.GetGrantInput{ + GrantArn: aws.String(arn), + } + + out, err := conn.GetGrantWithContext(ctx, in) + + if tfawserr.ErrCodeEquals(err, licensemanager.ErrCodeResourceNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + if out == nil || out.Grant == nil || aws.StringValue(out.Grant.GrantStatus) == licensemanager.GrantStatusDeleted || aws.StringValue(out.Grant.GrantStatus) == licensemanager.GrantStatusRejected { + return nil, tfresource.NewEmptyResultError(in) + } + + return out.Grant, nil +} + +func expandAllowedOperations(rawOperations []interface{}) []string { + if rawOperations == nil { + return nil + } + + operations := make([]string, 0, 8) + + for _, item := range rawOperations { + operations = append(operations, item.(string)) + } + + return operations +} diff --git a/internal/service/licensemanager/grant_accepter.go b/internal/service/licensemanager/grant_accepter.go new file mode 100644 index 00000000000..91aebbe3a24 --- /dev/null +++ b/internal/service/licensemanager/grant_accepter.go @@ -0,0 +1,181 @@ +package licensemanager + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/licensemanager" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" + "github.com/hashicorp/terraform-provider-aws/names" +) + +const ( + ResGrantAccepter = "Grant Accepter" +) + +// @SDKResource("aws_licensemanager_grant_accepter") +func ResourceGrantAccepter() *schema.Resource { + return &schema.Resource{ + CreateWithoutTimeout: resourceGrantAccepterCreate, + ReadWithoutTimeout: resourceGrantAccepterRead, + DeleteWithoutTimeout: resourceGrantAccepterDelete, + + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "allowed_operations": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "Allowed operations for the grant.", + }, + "home_region": { + Type: schema.TypeString, + Computed: true, + Description: "Home Region of the grant.", + }, + "license_arn": { + Type: schema.TypeString, + Computed: true, + Description: "License ARN.", + }, + "grant_arn": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidARN, + Description: "Amazon Resource Name (ARN) of the grant.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: "Name of the grant.", + }, + "parent_arn": { + Type: schema.TypeString, + Computed: true, + Description: "Parent ARN.", + }, + "principal": { + Type: schema.TypeString, + Computed: true, + Description: "The grantee principal ARN.", + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: "GrantAccepter status.", + }, + "version": { + Type: schema.TypeString, + Computed: true, + Description: "GrantAccepter version.", + }, + }, + } +} + +func resourceGrantAccepterCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + in := &licensemanager.AcceptGrantInput{ + GrantArn: aws.String(d.Get("grant_arn").(string)), + } + + out, err := conn.AcceptGrantWithContext(ctx, in) + + if err != nil { + return create.DiagError(names.LicenseManager, create.ErrActionCreating, ResGrantAccepter, d.Get("grant_arn").(string), err) + } + + d.SetId(aws.StringValue(out.GrantArn)) + + return resourceGrantAccepterRead(ctx, d, meta) +} + +func resourceGrantAccepterRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + out, err := FindGrantAccepterByGrantARN(ctx, conn, d.Id()) + + if !d.IsNewResource() && tfresource.NotFound(err) { + create.LogNotFoundRemoveState(names.LicenseManager, create.ErrActionReading, ResGrantAccepter, d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return create.DiagError(names.LicenseManager, create.ErrActionReading, ResGrantAccepter, d.Id(), err) + } + + d.Set("allowed_operations", out.GrantedOperations) + d.Set("grant_arn", out.GrantArn) + d.Set("home_region", out.HomeRegion) + d.Set("license_arn", out.LicenseArn) + d.Set("name", out.GrantName) + d.Set("parent_arn", out.ParentArn) + d.Set("principal", out.GranteePrincipalArn) + d.Set("status", out.GrantStatus) + d.Set("version", out.Version) + + return nil +} + +func resourceGrantAccepterDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + in := &licensemanager.RejectGrantInput{ + GrantArn: aws.String(d.Id()), + } + + _, err := conn.RejectGrantWithContext(ctx, in) + + if err != nil { + return create.DiagError(names.LicenseManager, create.ErrActionDeleting, ResGrantAccepter, d.Id(), err) + } + + return nil +} + +func FindGrantAccepterByGrantARN(ctx context.Context, conn *licensemanager.LicenseManager, arn string) (*licensemanager.Grant, error) { + in := &licensemanager.ListReceivedGrantsInput{ + GrantArns: aws.StringSlice([]string{arn}), + } + + out, err := conn.ListReceivedGrantsWithContext(ctx, in) + + if tfawserr.ErrCodeEquals(err, licensemanager.ErrCodeResourceNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + var entry *licensemanager.Grant + entryExists := false + + for _, grant := range out.Grants { + if arn == aws.StringValue(grant.GrantArn) && (licensemanager.GrantStatusActive == aws.StringValue(grant.GrantStatus) || licensemanager.GrantStatusDisabled == aws.StringValue(grant.GrantStatus)) { + entry = grant + entryExists = true + break + } + } + + if !entryExists { + return nil, tfresource.NewEmptyResultError(in) + } + + return entry, nil +} diff --git a/internal/service/licensemanager/grant_accepter_test.go b/internal/service/licensemanager/grant_accepter_test.go new file mode 100644 index 00000000000..f1fc33d996b --- /dev/null +++ b/internal/service/licensemanager/grant_accepter_test.go @@ -0,0 +1,188 @@ +package licensemanager_test + +import ( + "context" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go/service/licensemanager" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/envvar" + tflicensemanager "github.com/hashicorp/terraform-provider-aws/internal/service/licensemanager" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +func testAccGrantAccepter_basic(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + licenseARN := envvar.SkipIfEmpty(t, licenseARNKey, envVarLicenseARNKeyError) + principal := envvar.SkipIfEmpty(t, principalKey, envVarPrincipalKeyError) + homeRegion := envvar.SkipIfEmpty(t, homeRegionKey, envVarHomeRegionError) + resourceName := "aws_licensemanager_grant_accepter.test" + resourceGrantName := "aws_licensemanager_grant.test" + + providers := make(map[string]*schema.Provider) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(t) + }, + ErrorCheck: acctest.ErrorCheck(t, licensemanager.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5FactoriesNamed(ctx, t, providers), + CheckDestroy: acctest.CheckWithNamedProviders(testAccCheckGrantAccepterDestroyWithProvider(ctx), providers), + Steps: []resource.TestStep{ + { + Config: testAccGrantAccepterConfig_basic(licenseARN, rName, principal, homeRegion), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckGrantAccepterExists(ctx, resourceName, acctest.NamedProviderFunc(acctest.ProviderName, providers)), + resource.TestCheckResourceAttrPair(resourceName, "grant_arn", resourceGrantName, "arn"), + resource.TestCheckResourceAttrSet(resourceName, "allowed_operations.0"), + resource.TestCheckResourceAttrPair(resourceName, "home_region", resourceGrantName, "home_region"), + resource.TestCheckResourceAttr(resourceName, "license_arn", licenseARN), + resource.TestCheckResourceAttrPair(resourceName, "name", resourceGrantName, "name"), + resource.TestCheckResourceAttrPair(resourceName, "parent_arn", resourceGrantName, "parent_arn"), + resource.TestCheckResourceAttrPair(resourceName, "principal", resourceGrantName, "principal"), + resource.TestCheckResourceAttrSet(resourceName, "status"), + resource.TestCheckResourceAttrSet(resourceName, "version"), + ), + }, + { + Config: testAccGrantAccepterConfig_basic(licenseARN, rName, principal, homeRegion), + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccGrantAccepter_disappears(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + licenseARN := envvar.SkipIfEmpty(t, licenseARNKey, envVarLicenseARNKeyError) + principal := envvar.SkipIfEmpty(t, principalKey, envVarPrincipalKeyError) + homeRegion := envvar.SkipIfEmpty(t, homeRegionKey, envVarHomeRegionError) + resourceName := "aws_licensemanager_grant_accepter.test" + + providers := make(map[string]*schema.Provider) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(t) + }, + ErrorCheck: acctest.ErrorCheck(t, licensemanager.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5FactoriesNamed(ctx, t, providers), + CheckDestroy: acctest.CheckWithNamedProviders(testAccCheckGrantAccepterDestroyWithProvider(ctx), providers), + Steps: []resource.TestStep{ + { + Config: testAccGrantAccepterConfig_basic(licenseARN, rName, principal, homeRegion), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckGrantAccepterExists(ctx, resourceName, acctest.NamedProviderFunc(acctest.ProviderName, providers)), + acctest.CheckResourceDisappears(ctx, acctest.NamedProvider(acctest.ProviderName, providers), tflicensemanager.ResourceGrantAccepter(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckGrantAccepterExists(ctx context.Context, n string, providerF func() *schema.Provider) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No License Manager License Configuration ID is set") + } + + conn := providerF().Meta().(*conns.AWSClient).LicenseManagerConn() + + out, err := tflicensemanager.FindGrantAccepterByGrantARN(ctx, conn, rs.Primary.ID) + + if err != nil { + return err + } + + if out == nil { + return fmt.Errorf("GrantAccepter %q does not exist", rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckGrantAccepterDestroyWithProvider(ctx context.Context) acctest.TestCheckWithProviderFunc { + return func(s *terraform.State, provider *schema.Provider) error { + conn := provider.Meta().(*conns.AWSClient).LicenseManagerConn() + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_licensemanager_grant_accepter" { + continue + } + + _, err := tflicensemanager.FindGrantAccepterByGrantARN(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("License Manager GrantAccepter %s still exists", rs.Primary.ID) + } + + return nil + } +} + +func testAccGrantAccepterConfig_basic(licenseARN, rName, principal, homeRegion string) string { + principalArn, _ := arn.Parse(principal) + roleARN := arn.ARN{ + Partition: principalArn.Partition, + Service: "iam", + AccountID: principalArn.AccountID, + Resource: "role/OrganizationAccountAccessRole", + } + return acctest.ConfigCompose( + acctest.ConfigNamedRegionalProvider(acctest.ProviderNameAlternate, homeRegion), + fmt.Sprintf(` +provider %[1]q { + assume_role { + role_arn = %[2]q + } +}`, acctest.ProviderName, roleARN), + fmt.Sprintf(` +resource "aws_licensemanager_grant_accepter" "test" { + grant_arn = aws_licensemanager_grant.test.arn +} + +data "aws_licensemanager_received_license" "test" { + provider = awsalternate + license_arn = %[1]q +} + +locals { + allowed_operations = [for i in data.aws_licensemanager_received_license.test.received_metadata[0].allowed_operations : i if i != "CreateGrant"] +} + +resource "aws_licensemanager_grant" "test" { + provider = awsalternate + + name = %[2]q + allowed_operations = local.allowed_operations + license_arn = data.aws_licensemanager_received_license.test.license_arn + principal = %[3]q +} +`, licenseARN, rName, principal), + ) +} diff --git a/internal/service/licensemanager/grant_test.go b/internal/service/licensemanager/grant_test.go new file mode 100644 index 00000000000..fa4a2b7334b --- /dev/null +++ b/internal/service/licensemanager/grant_test.go @@ -0,0 +1,232 @@ +package licensemanager_test + +import ( + "context" + "fmt" + "regexp" + "testing" + + "github.com/aws/aws-sdk-go/service/licensemanager" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/envvar" + tflicensemanager "github.com/hashicorp/terraform-provider-aws/internal/service/licensemanager" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" +) + +const ( + homeRegionKey = "TF_AWS_LICENSE_MANAGER_GRANT_HOME_REGION" + licenseARNKey = "TF_AWS_LICENSE_MANAGER_GRANT_LICENSE_ARN" + principalKey = "TF_AWS_LICENSE_MANAGER_GRANT_PRINCIPAL" +) + +const ( + envVarHomeRegionError = "The region where the license has been imported into the current account." + envVarLicenseARNKeyError = "ARN for a license imported into the current account." + envVarPrincipalKeyError = "ARN of a principal to share the license with. Either a root user, Organization, or Organizational Unit." +) + +func TestAccLicenseManagerGrant_serial(t *testing.T) { + t.Parallel() + + testCases := map[string]map[string]func(t *testing.T){ + "grant": { + "basic": testAccGrant_basic, + "disappears": testAccGrant_disappears, + "name": testAccGrant_name, + }, + "grant_accepter": { + "basic": testAccGrantAccepter_basic, + "disappears": testAccGrantAccepter_disappears, + }, + "grant_data_source": { + "basic": testAccGrantsDataSource_basic, + "empty": testAccGrantsDataSource_noMatch, + }, + } + + acctest.RunSerialTests2Levels(t, testCases, 0) +} + +func testAccGrant_basic(t *testing.T) { + ctx := acctest.Context(t) + licenseARN := envvar.SkipIfEmpty(t, licenseARNKey, envVarLicenseARNKeyError) + principal := envvar.SkipIfEmpty(t, principalKey, envVarPrincipalKeyError) + homeRegion := envvar.SkipIfEmpty(t, homeRegionKey, envVarHomeRegionError) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_licensemanager_grant.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, licensemanager.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGrantDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGrantConfig_basic(licenseARN, rName, principal, homeRegion), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckGrantExists(ctx, resourceName), + acctest.MatchResourceAttrGlobalARN(resourceName, "arn", "license-manager", regexp.MustCompile(`grant:g-.+`)), + resource.TestCheckTypeSetElemAttr(resourceName, "allowed_operations.*", "ListPurchasedLicenses"), + resource.TestCheckTypeSetElemAttr(resourceName, "allowed_operations.*", "CheckoutLicense"), + resource.TestCheckTypeSetElemAttr(resourceName, "allowed_operations.*", "CheckInLicense"), + resource.TestCheckTypeSetElemAttr(resourceName, "allowed_operations.*", "ExtendConsumptionLicense"), + resource.TestCheckResourceAttr(resourceName, "home_region", homeRegion), + resource.TestCheckResourceAttr(resourceName, "license_arn", licenseARN), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttrSet(resourceName, "parent_arn"), + resource.TestCheckResourceAttr(resourceName, "principal", principal), + resource.TestCheckResourceAttr(resourceName, "status", "PENDING_ACCEPT"), + resource.TestCheckResourceAttr(resourceName, "version", "1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccGrant_disappears(t *testing.T) { + ctx := acctest.Context(t) + licenseARN := envvar.SkipIfEmpty(t, licenseARNKey, envVarLicenseARNKeyError) + principal := envvar.SkipIfEmpty(t, principalKey, envVarPrincipalKeyError) + homeRegion := envvar.SkipIfEmpty(t, homeRegionKey, envVarHomeRegionError) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_licensemanager_grant.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, licensemanager.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGrantDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGrantConfig_basic(licenseARN, rName, principal, homeRegion), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckGrantExists(ctx, resourceName), + acctest.CheckResourceDisappears(ctx, acctest.Provider, tflicensemanager.ResourceGrant(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccGrant_name(t *testing.T) { + ctx := acctest.Context(t) + licenseARN := envvar.SkipIfEmpty(t, licenseARNKey, envVarLicenseARNKeyError) + principal := envvar.SkipIfEmpty(t, principalKey, envVarPrincipalKeyError) + homeRegion := envvar.SkipIfEmpty(t, homeRegionKey, envVarHomeRegionError) + rName1 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + rName2 := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_licensemanager_grant.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, licensemanager.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckGrantDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccGrantConfig_basic(licenseARN, rName1, principal, homeRegion), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckGrantExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "name", rName1), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccGrantConfig_basic(licenseARN, rName2, principal, homeRegion), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckGrantExists(ctx, resourceName), + resource.TestCheckResourceAttr(resourceName, "name", rName2), + ), + }, + }, + }) +} + +func testAccCheckGrantExists(ctx context.Context, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No License Manager License Configuration ID is set") + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).LicenseManagerConn() + + out, err := tflicensemanager.FindGrantByARN(ctx, conn, rs.Primary.ID) + + if err != nil { + return err + } + + if out == nil { + return fmt.Errorf("Grant %q does not exist", rs.Primary.ID) + } + + return nil + } +} + +func testAccCheckGrantDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).LicenseManagerConn() + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_licensemanager_grant" { + continue + } + + _, err := tflicensemanager.FindGrantByARN(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + continue + } + + if err != nil { + return err + } + + return fmt.Errorf("License Manager Grant %s still exists", rs.Primary.ID) + } + + return nil + } +} + +func testAccGrantConfig_basic(licenseARN, rName, principal, homeRegion string) string { + return acctest.ConfigCompose( + acctest.ConfigRegionalProvider(homeRegion), + fmt.Sprintf(` +data "aws_licensemanager_received_license" "test" { + license_arn = %[1]q +} + +locals { + allowed_operations = [for i in data.aws_licensemanager_received_license.test.received_metadata[0].allowed_operations : i if i != "CreateGrant"] +} + +resource "aws_licensemanager_grant" "test" { + name = %[2]q + allowed_operations = local.allowed_operations + license_arn = data.aws_licensemanager_received_license.test.license_arn + principal = %[3]q +} +`, licenseARN, rName, principal), + ) +} diff --git a/internal/service/licensemanager/license_configuration_test.go b/internal/service/licensemanager/license_configuration_test.go index cba9f31d3f8..691991f8710 100644 --- a/internal/service/licensemanager/license_configuration_test.go +++ b/internal/service/licensemanager/license_configuration_test.go @@ -76,7 +76,7 @@ func TestAccLicenseManagerLicenseConfiguration_disappears(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccLicenseConfigurationConfig_basic(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckLicenseConfigurationExists(ctx, resourceName, &licenseConfiguration), acctest.CheckResourceDisappears(ctx, acctest.Provider, tflicensemanager.ResourceLicenseConfiguration(), resourceName), ), @@ -100,7 +100,7 @@ func TestAccLicenseManagerLicenseConfiguration_tags(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccLicenseConfigurationConfig_tags1(rName, "key1", "value1"), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckLicenseConfigurationExists(ctx, resourceName, &licenseConfiguration), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), @@ -113,7 +113,7 @@ func TestAccLicenseManagerLicenseConfiguration_tags(t *testing.T) { }, { Config: testAccLicenseConfigurationConfig_tags2(rName, "key1", "value1updated", "key2", "value2"), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckLicenseConfigurationExists(ctx, resourceName, &licenseConfiguration), resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), @@ -122,7 +122,7 @@ func TestAccLicenseManagerLicenseConfiguration_tags(t *testing.T) { }, { Config: testAccLicenseConfigurationConfig_tags1(rName, "key2", "value2"), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckLicenseConfigurationExists(ctx, resourceName, &licenseConfiguration), resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), diff --git a/internal/service/licensemanager/license_grants_data_source.go b/internal/service/licensemanager/license_grants_data_source.go new file mode 100644 index 00000000000..2e852c013ed --- /dev/null +++ b/internal/service/licensemanager/license_grants_data_source.go @@ -0,0 +1,92 @@ +package licensemanager + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/licensemanager" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" +) + +// @SDKDataSource("aws_licensemanager_grants") +func DataSourceDistributedGrants() *schema.Resource { + return &schema.Resource{ + ReadWithoutTimeout: dataSourceDistributedGrantsRead, + Schema: map[string]*schema.Schema{ + "filter": DataSourceFiltersSchema(), + "arns": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func dataSourceDistributedGrantsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + in := &licensemanager.ListDistributedGrantsInput{} + + in.Filters = BuildFiltersDataSource( + d.Get("filter").(*schema.Set), + ) + + if len(in.Filters) == 0 { + in.Filters = nil + } + + out, err := FindDistributedDistributedGrants(ctx, conn, in) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading Distributes Grants: %s", err) + } + + var grantARNs []string + + for _, v := range out { + grantARNs = append(grantARNs, aws.StringValue(v.GrantArn)) + } + + d.SetId(meta.(*conns.AWSClient).Region) + d.Set("arns", grantARNs) + + return diags +} + +func FindDistributedDistributedGrants(ctx context.Context, conn *licensemanager.LicenseManager, in *licensemanager.ListDistributedGrantsInput) ([]*licensemanager.Grant, error) { + var out []*licensemanager.Grant + + err := listDistributedGrantsPages(ctx, conn, in, func(page *licensemanager.ListDistributedGrantsOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, v := range page.Grants { + if v != nil { + out = append(out, v) + } + } + + return !lastPage + }) + + if tfawserr.ErrCodeEquals(err, licensemanager.ErrCodeResourceNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + return out, nil +} diff --git a/internal/service/licensemanager/license_grants_data_source_test.go b/internal/service/licensemanager/license_grants_data_source_test.go new file mode 100644 index 00000000000..ac951753086 --- /dev/null +++ b/internal/service/licensemanager/license_grants_data_source_test.go @@ -0,0 +1,90 @@ +package licensemanager_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/ec2" + sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/envvar" +) + +func testAccGrantsDataSource_basic(t *testing.T) { + ctx := acctest.Context(t) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + datasourceName := "data.aws_licensemanager_grants.test" + licenseARN := envvar.SkipIfEmpty(t, licenseARNKey, envVarLicenseARNKeyError) + principal := envvar.SkipIfEmpty(t, principalKey, envVarPrincipalKeyError) + homeRegion := envvar.SkipIfEmpty(t, homeRegionKey, envVarHomeRegionError) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5FactoriesAlternate(ctx, t), + Steps: []resource.TestStep{ + { + Config: testAccGrantsDataSourceConfig_basic(licenseARN, rName, principal, homeRegion), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet(datasourceName, "arns.0"), + ), + }, + }, + }) +} + +func testAccGrantsDataSource_noMatch(t *testing.T) { + datasourceName := "data.aws_licensemanager_grants.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccGrantsDataSourceConfig_noMatch(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(datasourceName, "arns.#", "0"), + ), + }, + }, + }) +} + +func testAccGrantsDataSourceConfig_basic(licenseARN, rName, principal, homeRegion string) string { + return acctest.ConfigCompose( + acctest.ConfigRegionalProvider(homeRegion), + acctest.ConfigAlternateAccountProvider(), + fmt.Sprintf(` +data "aws_licensemanager_received_license" "test" { + license_arn = %[1]q +} + +locals { + allowed_operations = [for i in data.aws_licensemanager_received_license.test.received_metadata[0].allowed_operations : i if i != "CreateGrant"] +} + +resource "aws_licensemanager_grant" "test" { + name = %[2]q + allowed_operations = local.allowed_operations + license_arn = data.aws_licensemanager_received_license.test.license_arn + principal = %[3]q +} + +data "aws_licensemanager_grants" "test" {} +`, licenseARN, rName, principal), + ) +} + +func testAccGrantsDataSourceConfig_noMatch() string { + return ` +data "aws_licensemanager_grants" "test" { + filter { + name = "LicenseIssuerName" + values = [ + "No Match" + ] + } +} +` +} diff --git a/internal/service/licensemanager/list_pages_gen.go b/internal/service/licensemanager/list_pages_gen.go index d1c6b5c136c..153408151ea 100644 --- a/internal/service/licensemanager/list_pages_gen.go +++ b/internal/service/licensemanager/list_pages_gen.go @@ -1,4 +1,4 @@ -// Code generated by "internal/generate/listpages/main.go -ListOps=ListLicenseConfigurations,ListLicenseSpecificationsForResource -ContextOnly"; DO NOT EDIT. +// Code generated by "internal/generate/listpages/main.go -ListOps=ListLicenseConfigurations,ListLicenseSpecificationsForResource,ListReceivedLicenses,ListDistributedGrants -ContextOnly"; DO NOT EDIT. package licensemanager @@ -10,6 +10,22 @@ import ( "github.com/aws/aws-sdk-go/service/licensemanager/licensemanageriface" ) +func listDistributedGrantsPages(ctx context.Context, conn licensemanageriface.LicenseManagerAPI, input *licensemanager.ListDistributedGrantsInput, fn func(*licensemanager.ListDistributedGrantsOutput, bool) bool) error { + for { + output, err := conn.ListDistributedGrantsWithContext(ctx, input) + if err != nil { + return err + } + + lastPage := aws.StringValue(output.NextToken) == "" + if !fn(output, lastPage) || lastPage { + break + } + + input.NextToken = output.NextToken + } + return nil +} func listLicenseConfigurationsPages(ctx context.Context, conn licensemanageriface.LicenseManagerAPI, input *licensemanager.ListLicenseConfigurationsInput, fn func(*licensemanager.ListLicenseConfigurationsOutput, bool) bool) error { for { output, err := conn.ListLicenseConfigurationsWithContext(ctx, input) @@ -42,3 +58,19 @@ func listLicenseSpecificationsForResourcePages(ctx context.Context, conn license } return nil } +func listReceivedLicensesPages(ctx context.Context, conn licensemanageriface.LicenseManagerAPI, input *licensemanager.ListReceivedLicensesInput, fn func(*licensemanager.ListReceivedLicensesOutput, bool) bool) error { + for { + output, err := conn.ListReceivedLicensesWithContext(ctx, input) + if err != nil { + return err + } + + lastPage := aws.StringValue(output.NextToken) == "" + if !fn(output, lastPage) || lastPage { + break + } + + input.NextToken = output.NextToken + } + return nil +} diff --git a/internal/service/licensemanager/received_license_data_source.go b/internal/service/licensemanager/received_license_data_source.go new file mode 100644 index 00000000000..de81b77eb7e --- /dev/null +++ b/internal/service/licensemanager/received_license_data_source.go @@ -0,0 +1,467 @@ +package licensemanager + +import ( + "context" + "errors" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/licensemanager" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/internal/verify" + "github.com/hashicorp/terraform-provider-aws/names" +) + +const ( + ResReceivedLicense = "Received License" +) + +// @SDKDataSource("aws_licensemanager_received_license") +func DataSourceReceivedLicense() *schema.Resource { + return &schema.Resource{ + ReadWithoutTimeout: dataSourceReceivedLicenseRead, + Schema: map[string]*schema.Schema{ + "beneficiary": { + Computed: true, + Type: schema.TypeString, + }, + "consumption_configuration": { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "borrow_configuration": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_early_check_in": { + Computed: true, + Type: schema.TypeBool, + }, + "max_time_to_live_in_minutes": { + Computed: true, + Type: schema.TypeInt, + }, + }, + }, + }, + "provisional_configuration": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_time_to_live_in_minutes": { + Computed: true, + Type: schema.TypeInt, + }, + }, + }, + }, + "renew_type": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "create_time": { + Computed: true, + Type: schema.TypeString, + }, + "entitlements": { + Computed: true, + Type: schema.TypeSet, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_check_in": { + Type: schema.TypeBool, + Computed: true, + }, + "max_count": { + Type: schema.TypeInt, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "unit": { + Type: schema.TypeString, + Computed: true, + }, + "value": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "home_region": { + Computed: true, + Type: schema.TypeString, + }, + "issuer": { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key_fingerprint": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "sign_key": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "license_arn": { + Required: true, + Type: schema.TypeString, + ValidateFunc: verify.ValidARN, + }, + "license_metadata": { + Computed: true, + Type: schema.TypeSet, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "value": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "license_name": { + Computed: true, + Type: schema.TypeString, + }, + "product_name": { + Computed: true, + Type: schema.TypeString, + }, + "product_sku": { + Computed: true, + Type: schema.TypeString, + }, + "received_metadata": { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allowed_operations": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "received_status": { + Type: schema.TypeString, + Computed: true, + }, + "received_status_reason": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "status": { + Computed: true, + Type: schema.TypeString, + }, + "validity": { + Computed: true, + Type: schema.TypeList, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "begin": { + Type: schema.TypeString, + Computed: true, + }, + "end": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "version": { + Computed: true, + Type: schema.TypeString, + }, + }, + } +} + +func dataSourceReceivedLicenseRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + arn := d.Get("license_arn").(string) + + in := &licensemanager.ListReceivedLicensesInput{ + LicenseArns: aws.StringSlice([]string{arn}), + } + + out, err := FindReceivedLicenseByARN(ctx, conn, in) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading License Manager Received License (%s): %s", arn, err) + } + + d.SetId(aws.StringValue(out.LicenseArn)) + d.Set("beneficiary", out.Beneficiary) + d.Set("consumption_configuration", []interface{}{flattenConsumptionConfiguration(out.ConsumptionConfiguration)}) + d.Set("entitlements", flattenEntitlements(out.Entitlements)) + d.Set("home_region", out.HomeRegion) + d.Set("issuer", []interface{}{flattenIssuer(out.Issuer)}) + d.Set("license_arn", out.LicenseArn) + d.Set("license_metadata", flattenMetadatas(out.LicenseMetadata)) + d.Set("license_name", out.LicenseName) + d.Set("product_name", out.ProductName) + d.Set("product_sku", out.ProductSKU) + d.Set("received_metadata", []interface{}{flattenReceivedMetadata(out.ReceivedMetadata)}) + d.Set("status", out.Status) + d.Set("validity", []interface{}{flattenDateTimeRange(out.Validity)}) + d.Set("version", out.Version) + + if v := aws.StringValue(out.CreateTime); v != "" { + seconds, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading License Manager Received License (%s): %s", arn, err) + } + d.Set("create_time", time.Unix(seconds, 0).UTC().Format(time.RFC3339)) + } + + return diags +} + +func FindReceivedLicenseByARN(ctx context.Context, conn *licensemanager.LicenseManager, in *licensemanager.ListReceivedLicensesInput) (*licensemanager.GrantedLicense, error) { + out, err := conn.ListReceivedLicensesWithContext(ctx, in) + + if tfawserr.ErrCodeEquals(err, licensemanager.ErrCodeResourceNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + if len(out.Licenses) == 0 { + return nil, tfresource.NewEmptyResultError(in) + } + + if len(out.Licenses) > 1 { + return nil, create.Error(names.LicenseManager, create.ErrActionReading, ResReceivedLicense, *in.LicenseArns[0], errors.New("More than one License Returned by the API.")) + } + + return out.Licenses[0], nil +} + +func flattenConsumptionConfiguration(apiObject *licensemanager.ConsumptionConfiguration) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.BorrowConfiguration; v != nil { + tfMap["borrow_configuration"] = map[string]interface{}{ + "max_time_to_live_in_minutes": v.MaxTimeToLiveInMinutes, + "allow_early_check_in": v.AllowEarlyCheckIn, + } + } + + if v := apiObject.ProvisionalConfiguration.MaxTimeToLiveInMinutes; v != nil { + tfMap["provisional_configuration"] = []interface{}{map[string]interface{}{ + "max_time_to_live_in_minutes": int(aws.Int64Value(v)), + }} + } + + if v := apiObject.RenewType; v != nil { + tfMap["renew_type"] = v + } + + return tfMap +} + +func flattenEntitlements(apiObjects []*licensemanager.Entitlement) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var tfList []interface{} + + for _, apiObject := range apiObjects { + if apiObject == nil { + continue + } + + out := flattenEntitlement(apiObject) + + if len(out) > 0 { + tfList = append(tfList, out) + } + } + + return tfList +} + +func flattenEntitlement(apiObject *licensemanager.Entitlement) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.AllowCheckIn; v != nil { + tfMap["allow_check_in"] = v + } + + if v := apiObject.MaxCount; v != nil { + tfMap["max_count"] = v + } + + if v := apiObject.Name; v != nil { + tfMap["name"] = v + } + + if v := apiObject.Overage; v != nil { + tfMap["overage"] = v + } + + if v := apiObject.Unit; v != nil { + tfMap["unit"] = v + } + + if v := apiObject.Value; v != nil { + tfMap["value"] = v + } + + return tfMap +} + +func flattenIssuer(apiObject *licensemanager.IssuerDetails) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.KeyFingerprint; v != nil { + tfMap["key_fingerprint"] = v + } + + if v := apiObject.Name; v != nil { + tfMap["name"] = v + } + + if v := apiObject.SignKey; v != nil { + tfMap["sign_key"] = v + } + + return tfMap +} + +func flattenMetadatas(apiObjects []*licensemanager.Metadata) []interface{} { + if len(apiObjects) == 0 { + return nil + } + + var tfList []interface{} + + for _, apiObject := range apiObjects { + if apiObject == nil { + continue + } + + out := flattenLicenseMetadata(apiObject) + + if len(out) > 0 { + tfList = append(tfList, out) + } + } + + return tfList +} + +func flattenLicenseMetadata(apiObject *licensemanager.Metadata) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.Name; v != nil { + tfMap["name"] = v + } + + if v := apiObject.Value; v != nil { + tfMap["value"] = v + } + + return tfMap +} + +func flattenReceivedMetadata(apiObject *licensemanager.ReceivedMetadata) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.AllowedOperations; v != nil { + tfMap["allowed_operations"] = v + } + + if v := apiObject.ReceivedStatus; v != nil { + tfMap["received_status"] = v + } + + if v := apiObject.ReceivedStatusReason; v != nil { + tfMap["received_status_reason"] = v + } + + return tfMap +} + +func flattenDateTimeRange(apiObject *licensemanager.DatetimeRange) map[string]interface{} { + if apiObject == nil { + return nil + } + + tfMap := map[string]interface{}{} + + if v := apiObject.Begin; v != nil { + tfMap["begin"] = v + } + + if v := apiObject.End; v != nil { + tfMap["end"] = v + } + + return tfMap +} diff --git a/internal/service/licensemanager/received_license_data_source_test.go b/internal/service/licensemanager/received_license_data_source_test.go new file mode 100644 index 00000000000..e62dfcbb42a --- /dev/null +++ b/internal/service/licensemanager/received_license_data_source_test.go @@ -0,0 +1,53 @@ +package licensemanager_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/envvar" +) + +func TestAccLicenseManagerReceivedLicenseDataSource_basic(t *testing.T) { + datasourceName := "data.aws_licensemanager_received_license.test" + licenseARN := envvar.SkipIfEmpty(t, licenseARNKey, envVarLicenseARNKeyError) + homeRegion := envvar.SkipIfEmpty(t, homeRegionKey, envVarHomeRegionError) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccReceivedLicenseDataSourceConfig_arn(licenseARN), + Check: resource.ComposeAggregateTestCheckFunc( + acctest.CheckResourceAttrGlobalARN(datasourceName, "beneficiary", "iam", "root"), + resource.TestCheckResourceAttr(datasourceName, "consumption_configuration.#", "1"), + acctest.CheckResourceAttrRFC3339(datasourceName, "create_time"), + resource.TestCheckResourceAttr(datasourceName, "entitlements.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "home_region", homeRegion), + resource.TestCheckResourceAttr(datasourceName, "issuer.#", "1"), + resource.TestCheckResourceAttr(datasourceName, "license_arn", licenseARN), + resource.TestCheckResourceAttrSet(datasourceName, "license_metadata.0.%"), + resource.TestCheckResourceAttrSet(datasourceName, "license_name"), + resource.TestCheckResourceAttrSet(datasourceName, "product_name"), + resource.TestCheckResourceAttrSet(datasourceName, "product_sku"), + resource.TestCheckResourceAttr(datasourceName, "received_metadata.#", "1"), + resource.TestCheckResourceAttrSet(datasourceName, "status"), + resource.TestCheckResourceAttr(datasourceName, "validity.#", "1"), + resource.TestCheckResourceAttrSet(datasourceName, "version"), + ), + }, + }, + }) +} + +func testAccReceivedLicenseDataSourceConfig_arn(licenseARN string) string { + return fmt.Sprintf(` +data "aws_licensemanager_received_license" "test" { + license_arn = %[1]q +} +`, licenseARN) +} diff --git a/internal/service/licensemanager/received_licenses_data_source.go b/internal/service/licensemanager/received_licenses_data_source.go new file mode 100644 index 00000000000..01305a94e9e --- /dev/null +++ b/internal/service/licensemanager/received_licenses_data_source.go @@ -0,0 +1,92 @@ +package licensemanager + +import ( + "context" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/licensemanager" + "github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" +) + +// @SDKDataSource("aws_licensemanager_received_licenses") +func DataSourceReceivedLicenses() *schema.Resource { + return &schema.Resource{ + ReadWithoutTimeout: dataSourceReceivedLicensesRead, + Schema: map[string]*schema.Schema{ + "arns": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "filter": DataSourceFiltersSchema(), + }, + } +} + +func dataSourceReceivedLicensesRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).LicenseManagerConn() + + in := &licensemanager.ListReceivedLicensesInput{} + + in.Filters = BuildFiltersDataSource( + d.Get("filter").(*schema.Set), + ) + + if len(in.Filters) == 0 { + in.Filters = nil + } + + out, err := FindReceivedLicenses(ctx, conn, in) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading Received Licenses: %s", err) + } + + var licenseARNs []string + + for _, v := range out { + licenseARNs = append(licenseARNs, aws.StringValue(v.LicenseArn)) + } + + d.SetId(meta.(*conns.AWSClient).Region) + d.Set("arns", licenseARNs) + + return diags +} + +func FindReceivedLicenses(ctx context.Context, conn *licensemanager.LicenseManager, in *licensemanager.ListReceivedLicensesInput) ([]*licensemanager.GrantedLicense, error) { + var out []*licensemanager.GrantedLicense + + err := listReceivedLicensesPages(ctx, conn, in, func(page *licensemanager.ListReceivedLicensesOutput, lastPage bool) bool { + if page == nil { + return !lastPage + } + + for _, v := range page.Licenses { + if v != nil { + out = append(out, v) + } + } + + return !lastPage + }) + + if tfawserr.ErrCodeEquals(err, licensemanager.ErrCodeResourceNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + return out, nil +} diff --git a/internal/service/licensemanager/received_licenses_data_source_test.go b/internal/service/licensemanager/received_licenses_data_source_test.go new file mode 100644 index 00000000000..8049475c3d9 --- /dev/null +++ b/internal/service/licensemanager/received_licenses_data_source_test.go @@ -0,0 +1,77 @@ +package licensemanager_test + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/envvar" +) + +func TestAccLicenseManagerReceivedLicensesDataSource_basic(t *testing.T) { + datasourceName := "data.aws_licensemanager_received_licenses.test" + licenseARN := envvar.SkipIfEmpty(t, licenseARNKey, envVarLicenseARNKeyError) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccReceivedLicensesDataSourceConfig_arns(licenseARN), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(datasourceName, "arns.#", "1"), + ), + }, + }, + }) +} + +func TestAccLicenseManagerReceivedLicensesDataSource_empty(t *testing.T) { + datasourceName := "data.aws_licensemanager_received_licenses.test" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccReceivedLicensesDataSourceConfig_empty(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(datasourceName, "arns.#", "0"), + ), + }, + }, + }) +} + +func testAccReceivedLicensesDataSourceConfig_arns(licenseARN string) string { + return fmt.Sprintf(` +data "aws_licensemanager_received_licenses" "test" { + filter { + name = "ProductSKU" + values = [ + data.aws_licensemanager_received_license.test.product_sku + ] + } +} + +data "aws_licensemanager_received_license" "test" { + license_arn = %[1]q +} +`, licenseARN) +} + +func testAccReceivedLicensesDataSourceConfig_empty() string { + return ` +data "aws_licensemanager_received_licenses" "test" { + filter { + name = "IssuerName" + values = [ + "This Is Fake" + ] + } +} +` +} diff --git a/internal/service/licensemanager/service_package_gen.go b/internal/service/licensemanager/service_package_gen.go index 95a597c48bf..7597b93f190 100644 --- a/internal/service/licensemanager/service_package_gen.go +++ b/internal/service/licensemanager/service_package_gen.go @@ -20,7 +20,20 @@ func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.Servic } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { - return []*types.ServicePackageSDKDataSource{} + return []*types.ServicePackageSDKDataSource{ + { + Factory: DataSourceDistributedGrants, + TypeName: "aws_licensemanager_grants", + }, + { + Factory: DataSourceReceivedLicense, + TypeName: "aws_licensemanager_received_license", + }, + { + Factory: DataSourceReceivedLicenses, + TypeName: "aws_licensemanager_received_licenses", + }, + } } func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePackageSDKResource { @@ -29,6 +42,14 @@ func (p *servicePackage) SDKResources(ctx context.Context) []*types.ServicePacka Factory: ResourceAssociation, TypeName: "aws_licensemanager_association", }, + { + Factory: ResourceGrant, + TypeName: "aws_licensemanager_grant", + }, + { + Factory: ResourceGrantAccepter, + TypeName: "aws_licensemanager_grant_accepter", + }, { Factory: ResourceLicenseConfiguration, TypeName: "aws_licensemanager_license_configuration", diff --git a/website/docs/d/licensemanager_grants.html.markdown b/website/docs/d/licensemanager_grants.html.markdown new file mode 100644 index 00000000000..8369ffc24f8 --- /dev/null +++ b/website/docs/d/licensemanager_grants.html.markdown @@ -0,0 +1,54 @@ +--- +subcategory: "License Manager" +layout: "aws" +page_title: "AWS: aws_licensemanager_grants" +description: |- + Get information about a set of license manager grant licenses +--- + +# Data Source: aws_licensemanager_grants + +This resource can be used to get a set of license grant ARNs matching a filter. + +## Example Usage + +The following shows getting all license grant ARNs granted to your account. + +```terraform +data "aws_caller_identity" "current" {} + +data "aws_licensemanager_grants" "test" { + filter { + name = "GranteePrincipalARN" + values = [ + "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + ] + } +} +``` + +## Argument Reference + +* `filter` - (Optional) Custom filter block as described below. + +More complex filters can be expressed using one or more `filter` sub-blocks, +which take the following arguments: + +* `name` - (Required) Name of the field to filter by, as defined by + [the underlying AWS API](https://docs.aws.amazon.com/license-manager/latest/APIReference/API_ListReceivedGrants.html#API_ListReceivedGrants_RequestSyntax). + For example, if filtering using `ProductSKU`, use: + +```terraform +data "aws_licensemanager_grants" "selected" { + filter { + name = "ProductSKU" + values = [""] # insert values here + } +} +``` + +* `values` - (Required) Set of values that are accepted for the given field. + +## Attributes Reference + +* `arns` - List of all the license grant ARNs found. diff --git a/website/docs/d/licensemanager_received_license.html.markdown b/website/docs/d/licensemanager_received_license.html.markdown new file mode 100644 index 00000000000..102fd521bde --- /dev/null +++ b/website/docs/d/licensemanager_received_license.html.markdown @@ -0,0 +1,104 @@ +--- +subcategory: "License Manager" +layout: "aws" +page_title: "AWS: aws_licensemanager_received_license" +description: |- + Get information about a set of license manager received license +--- + +# Data Source: aws_licensemanager_received_license + +This resource can be used to get data on a received license using an ARN. This can be helpful for pulling in data on a license from the AWS marketplace and sharing that license with another account. + +## Example Usage + +The following shows getting the received license data using and ARN. + +```terraform +data "aws_licensemanager_received_license" "test" { + license_arn = "arn:aws:license-manager::111111111111:license:l-ecbaa94eb71a4830b6d7e49268fecaa0" +} +``` + +## Argument Reference + +* `license_arn` - (Required) The ARN of the received license you want data for. + +## Attributes Reference + +* `id` - The received license ARN (Same as: `license_arn`). +* `beneficiary` - Granted license beneficiary. This is in the form of the ARN of the root user of the account. +* `consumption_configuration` - Configuration for consumption of the license. [Detailed below](#consumption_configuration) +* `create_time` - Creation time of the granted license in RFC 3339 format. +* `entitlements` - License entitlements. [Detailed below](#entitlements) +* `home_region` - Home Region of the granted license. +* `issuer` - Granted license issuer. [Detailed below](#issuer) +* `license_arn` - Amazon Resource Name (ARN) of the license. +* `license_metadata`- Granted license metadata. This is in the form of a set of all meta data. [Detailed below](#license_metadata) +* `license_name` - License name. +* `product_name` - Product name. +* `product_sku ` - Product SKU. +* `received_metadata` - Granted license received metadata. [Detailed below](#received_metadata) +* `status` - Granted license status. +* `validity` - Date and time range during which the granted license is valid, in ISO8601-UTC format. [Detailed below](#validity) +* `version` - Version of the granted license. + +### consumption_configuration + +* `borrow_configuration` - Details about a borrow configuration. [Detailed below](#borrow_configuration) +* `provisional_configuration` - Details about a provisional configuration. [Detailed below](#provisional_configuration) +* `renewal_frequency` - Renewal frequency. + +#### borrow_configuration + +A list with a single map. + +* `allow_early_check_in` - Indicates whether early check-ins are allowed. +* `max_time_to_live_in_minutes` - Maximum time for the borrow configuration, in minutes. + +#### provisional_configuration + +A list with a single map. + +* `max_time_to_live_in_minutes` - Maximum time for the provisional configuration, in minutes. + +### entitlements + +A list with a single map. + +* `allow_check_in` - Indicates whether check-ins are allowed. +* `max_count` - Maximum entitlement count. Use if the unit is not None. +* `name` - Entitlement name. +* `overage` - Indicates whether overages are allowed. +* `unit` - Entitlement unit. +* `value` - Entitlement resource. Use only if the unit is None. + +### issuer + +A list with a single map. + +* `key_fingerprint` - Issuer key fingerprint. +* `name` - Issuer name. +* `sign_key` - Asymmetric KMS key from AWS Key Management Service. The KMS key must have a key usage of sign and verify, and support the RSASSA-PSS SHA-256 signing algorithm. + +### license_metadata + +Each metadata item will have the following attributes. + +* `name` - The key name. +* `value` - The value. + +### received_metadata + +A list with a single map. + +* `allowed_operations` - A list of allowed operations. +* `received_status` - Received status. +* `received_status_reason` - Received status reason. + +### validity + +A list with a single map. + +* `begin` - Start of the validity time range. +* `end` - End of the validity time range. diff --git a/website/docs/d/licensemanager_received_licenses.html.markdown b/website/docs/d/licensemanager_received_licenses.html.markdown new file mode 100644 index 00000000000..6a36d53e184 --- /dev/null +++ b/website/docs/d/licensemanager_received_licenses.html.markdown @@ -0,0 +1,52 @@ +--- +subcategory: "License Manager" +layout: "aws" +page_title: "AWS: aws_licensemanager_received_licenses" +description: |- + Get information about a set of license manager received licenses +--- + +# Data Source: aws_licensemanager_received_licenses + +This resource can be used to get a set of license ARNs matching a filter. + +## Example Usage + +The following shows getting all license ARNs issued from the AWS marketplace. Providing no filter, would provide all license ARNs for the entire account. + +```terraform +data "aws_licensemanager_received_licenses" "test" { + filter { + name = "IssuerName" + values = [ + "AWS/Marketplace" + ] + } +} +``` + +## Argument Reference + +* `filter` - (Optional) Custom filter block as described below. + +More complex filters can be expressed using one or more `filter` sub-blocks, +which take the following arguments: + +* `name` - (Required) Name of the field to filter by, as defined by + [the underlying AWS API](https://docs.aws.amazon.com/license-manager/latest/APIReference/API_ListReceivedLicenses.html#API_ListReceivedLicenses_RequestSyntax). + For example, if filtering using `ProductSKU`, use: + +```terraform +data "aws_licensemanager_received_licenses" "selected" { + filter { + name = "ProductSKU" + values = [""] # insert values here + } +} +``` + +* `values` - (Required) Set of values that are accepted for the given field. + +## Attributes Reference + +* `arns` - List of all the license ARNs found. diff --git a/website/docs/r/licensemanager_grant.html.markdown b/website/docs/r/licensemanager_grant.html.markdown new file mode 100644 index 00000000000..95e95b17b8c --- /dev/null +++ b/website/docs/r/licensemanager_grant.html.markdown @@ -0,0 +1,57 @@ +--- +subcategory: "License Manager" +layout: "aws" +page_title: "AWS: aws_licensemanager_grant" +description: |- + Provides a License Manager grant resource. +--- + +# Resource: aws_licensemanager_grant + +Provides a License Manager grant. This allows for sharing licenses with other AWS accounts. + +## Example Usage + +```terraform +resource "aws_licensemanager_grant" "test" { + name = "share-license-with-account" + allowed_operations = [ + "ListPurchasedLicenses", + "CheckoutLicense", + "CheckInLicense", + "ExtendConsumptionLicense", + "CreateToken" + ] + license_arn = "arn:aws:license-manager::111111111111:license:l-exampleARN" + principal = "arn:aws:iam::111111111112:root" + home_region = "us-east-1" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The Name of the grant. +* `allowed_operations` - (Required) A list of the allowed operations for the grant. This is a subset of the allowed operations on the license. +* `license_arn` - (Required) The ARN of the license to grant. +* `principal` - (Required) The target account for the grant in the form of the ARN for an account principal of the root user. +* `home_region` - (Required) The home region for the license. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The grant ARN (Same as `arn`). +* `arn` - The grant ARN. +* `parent_arn` - The parent ARN. +* `status` - The grant status. +* `version` - The grant version. + +## Import + +`aws_licensemanager_grant` can be imported using the grant arn. + +```shell +$ terraform import aws_licensemanager_grant.test arn:aws:license-manager::123456789011:grant:g-01d313393d9e443d8664cc054db1e089 +``` diff --git a/website/docs/r/licensemanager_grant_accepter.html.markdown b/website/docs/r/licensemanager_grant_accepter.html.markdown new file mode 100644 index 00000000000..6d81eea415f --- /dev/null +++ b/website/docs/r/licensemanager_grant_accepter.html.markdown @@ -0,0 +1,48 @@ +--- +subcategory: "License Manager" +layout: "aws" +page_title: "AWS: aws_licensemanager_grant_accepter" +description: |- + Accepts a License Manager grant resource. +--- + +# Resource: aws_licensemanager_grant_accepter + +Accepts a License Manager grant. This allows for sharing licenses with other aws accounts. + +## Example Usage + +```terraform +resource "aws_licensemanager_grant_accepter" "test" { + name = "arn:aws:license-manager::123456789012:grant:g-1cf9fba4ba2f42dcab11c686c4b4d329" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `grant_arn` - (Required) The ARN of the grant to accept. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The grant ARN (Same as `arn`). +* `arn` - The grant ARN. +* `name` - The Name of the grant. +* `allowed_operations` - A list of the allowed operations for the grant. +* `license_arn` - The ARN of the license for the grant. +* `principal` - The target account for the grant. +* `home_region` - The home region for the license. +* `parent_arn` - The parent ARN. +* `status` - The grant status. +* `version` - The grant version. + +## Import + +`aws_licensemanager_grant_accepter` can be imported using the grant arn. + +```shell +$ terraform import aws_licensemanager_grant_accepter.test arn:aws:license-manager::123456789012:grant:g-1cf9fba4ba2f42dcab11c686c4b4d329 +```