Skip to content

Commit

Permalink
r/eks_addon: Deprecate resolve_conflicts attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
mattburgess committed Feb 21, 2023
1 parent 0dd0781 commit ac087fc
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 25 deletions.
35 changes: 33 additions & 2 deletions internal/service/eks/addon.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,22 @@ func ResourceAddon() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(eks.ResolveConflicts_Values(), false),
Deprecated: "The \"resolve_conflicts\" attribute can't be set to \"PRESERVE\" on initial resource creation. Use \"resolve_conflicts_on_create\" and \"resolve_conflicts_on_update\" instead",
},
"resolve_conflicts_on_create": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
eks.ResolveConflictsNone,
eks.ResolveConflictsOverwrite,
}, false),
ConflictsWith: []string{"resolve_conflicts"},
},
"resolve_conflicts_on_update": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(eks.ResolveConflicts_Values(), false),
ConflictsWith: []string{"resolve_conflicts"},
},
"service_account_role_arn": {
Type: schema.TypeString,
Expand Down Expand Up @@ -117,6 +133,10 @@ func resourceAddonCreate(ctx context.Context, d *schema.ResourceData, meta inter
input.AddonVersion = aws.String(v.(string))
}

if v, ok := d.GetOk("resolve_conflicts_on_create"); ok {
input.ResolveConflicts = aws.String(v.(string))
}

if v, ok := d.GetOk("resolve_conflicts"); ok {
input.ResolveConflicts = aws.String(v.(string))
}
Expand Down Expand Up @@ -250,7 +270,18 @@ func resourceAddonUpdate(ctx context.Context, d *schema.ResourceData, meta inter
input.ConfigurationValues = aws.String(d.Get("configuration_values").(string))
}

conflictResolutionAttr := ""
conflictResolution := ""

if v, ok := d.GetOk("resolve_conflicts"); ok {
conflictResolutionAttr = "resolve_conflicts"
conflictResolution = v.(string)
input.ResolveConflicts = aws.String(v.(string))
}

if v, ok := d.GetOk("resolve_conflicts_on_update"); ok {
conflictResolutionAttr = "resolve_conflicts_on_update"
conflictResolution = v.(string)
input.ResolveConflicts = aws.String(v.(string))
}

Expand All @@ -271,12 +302,12 @@ func resourceAddonUpdate(ctx context.Context, d *schema.ResourceData, meta inter
_, err = waitAddonUpdateSuccessful(ctx, conn, clusterName, addonName, updateID, d.Timeout(schema.TimeoutUpdate))

if err != nil {
if d.Get("resolve_conflicts") != eks.ResolveConflictsOverwrite {
if conflictResolution != eks.ResolveConflictsOverwrite {
// Changing addon version w/o setting resolve_conflicts to "OVERWRITE"
// might result in a failed update if there are conflicts:
// ConfigurationConflict Apply failed with 1 conflict: conflict with "kubectl"...
return diag.FromErr(fmt.Errorf("error waiting for EKS Add-On (%s) update (%s): %w, consider setting attribute %q to %q",
d.Id(), updateID, err, "resolve_conflicts", eks.ResolveConflictsOverwrite))
d.Id(), updateID, err, conflictResolutionAttr, eks.ResolveConflictsOverwrite))
}

return diag.FromErr(fmt.Errorf("error waiting for EKS Add-On (%s) update (%s): %w", d.Id(), updateID, err))
Expand Down
73 changes: 66 additions & 7 deletions internal/service/eks/addon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func TestAccEKSAddon_addonVersion(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"resolve_conflicts"},
ImportStateVerifyIgnore: []string{"resolve_conflicts_on_create", "resolve_conflicts_on_update"},
},
{
Config: testAccAddonConfig_version(rName, addonName, addonVersion2),
Expand Down Expand Up @@ -173,7 +173,7 @@ func TestAccEKSAddon_preserve(t *testing.T) {
})
}

func TestAccEKSAddon_resolveConflicts(t *testing.T) {
func TestAccEKSAddon_deprecated(t *testing.T) {
ctx := acctest.Context(t)
var addon1, addon2, addon3 eks.Addon
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand All @@ -187,7 +187,7 @@ func TestAccEKSAddon_resolveConflicts(t *testing.T) {
CheckDestroy: testAccCheckAddonDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccAddonConfig_resolveConflicts(rName, addonName, eks.ResolveConflictsNone),
Config: testAccAddonConfig_deprecated(rName, addonName, eks.ResolveConflictsNone),
Check: resource.ComposeTestCheckFunc(
testAccCheckAddonExists(ctx, resourceName, &addon1),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts", eks.ResolveConflictsNone),
Expand All @@ -200,14 +200,14 @@ func TestAccEKSAddon_resolveConflicts(t *testing.T) {
ImportStateVerifyIgnore: []string{"resolve_conflicts"},
},
{
Config: testAccAddonConfig_resolveConflicts(rName, addonName, eks.ResolveConflictsOverwrite),
Config: testAccAddonConfig_deprecated(rName, addonName, eks.ResolveConflictsOverwrite),
Check: resource.ComposeTestCheckFunc(
testAccCheckAddonExists(ctx, resourceName, &addon2),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts", eks.ResolveConflictsOverwrite),
),
},
{
Config: testAccAddonConfig_resolveConflicts(rName, addonName, eks.ResolveConflictsPreserve),
Config: testAccAddonConfig_deprecated(rName, addonName, eks.ResolveConflictsPreserve),
Check: resource.ComposeTestCheckFunc(
testAccCheckAddonExists(ctx, resourceName, &addon3),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts", eks.ResolveConflictsPreserve),
Expand All @@ -217,6 +217,53 @@ func TestAccEKSAddon_resolveConflicts(t *testing.T) {
})
}

func TestAccEKSAddon_resolveConflicts(t *testing.T) {
ctx := acctest.Context(t)
var addon1, addon2, addon3 eks.Addon
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_eks_addon.test"
addonName := "vpc-cni"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); testAccPreCheck(ctx, t); testAccPreCheckAddon(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, eks.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckAddonDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccAddonConfig_resolveConflicts(rName, addonName, eks.ResolveConflictsNone, eks.ResolveConflictsNone),
Check: resource.ComposeTestCheckFunc(
testAccCheckAddonExists(ctx, resourceName, &addon1),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts_on_create", eks.ResolveConflictsNone),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts_on_update", eks.ResolveConflictsNone),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"resolve_conflicts_on_create", "resolve_conflicts_on_update"},
},
{
Config: testAccAddonConfig_resolveConflicts(rName, addonName, eks.ResolveConflictsOverwrite, eks.ResolveConflictsOverwrite),
Check: resource.ComposeTestCheckFunc(
testAccCheckAddonExists(ctx, resourceName, &addon2),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts_on_create", eks.ResolveConflictsOverwrite),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts_on_update", eks.ResolveConflictsOverwrite),
),
},
{
Config: testAccAddonConfig_resolveConflicts(rName, addonName, eks.ResolveConflictsOverwrite, eks.ResolveConflictsPreserve),
Check: resource.ComposeTestCheckFunc(
testAccCheckAddonExists(ctx, resourceName, &addon3),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts_on_create", eks.ResolveConflictsOverwrite),
resource.TestCheckResourceAttr(resourceName, "resolve_conflicts_on_update", eks.ResolveConflictsPreserve),
),
},
},
})
}

func TestAccEKSAddon_serviceAccountRoleARN(t *testing.T) {
ctx := acctest.Context(t)
var addon eks.Addon
Expand Down Expand Up @@ -887,7 +934,8 @@ resource "aws_eks_addon" "test" {
cluster_name = aws_eks_cluster.test.name
addon_name = %[2]q
addon_version = %[3]q
resolve_conflicts = "OVERWRITE"
resolve_conflicts_on_create = "OVERWRITE"
resolve_conflicts_on_update = "OVERWRITE"
}
`, rName, addonName, addonVersion))
}
Expand All @@ -902,7 +950,7 @@ resource "aws_eks_addon" "test" {
`, rName, addonName))
}

func testAccAddonConfig_resolveConflicts(rName, addonName, resolveConflicts string) string {
func testAccAddonConfig_deprecated(rName, addonName, resolveConflicts string) string {
return acctest.ConfigCompose(testAccAddonConfig_base(rName), fmt.Sprintf(`
resource "aws_eks_addon" "test" {
cluster_name = aws_eks_cluster.test.name
Expand All @@ -912,6 +960,17 @@ resource "aws_eks_addon" "test" {
`, rName, addonName, resolveConflicts))
}

func testAccAddonConfig_resolveConflicts(rName, addonName, resolveConflictsOnCreate, resolveConflictsOnUpdate string) string {
return acctest.ConfigCompose(testAccAddonConfig_base(rName), fmt.Sprintf(`
resource "aws_eks_addon" "test" {
cluster_name = aws_eks_cluster.test.name
addon_name = %[2]q
resolve_conflicts_on_create = %[3]q
resolve_conflicts_on_update = %[4]q
}
`, rName, addonName, resolveConflictsOnCreate, resolveConflictsOnUpdate))
}

func testAccAddonConfig_serviceAccountRoleARN(rName, addonName string) string {
return acctest.ConfigCompose(testAccAddonConfig_base(rName), fmt.Sprintf(`
resource "aws_iam_role" "test-service-role" {
Expand Down
43 changes: 27 additions & 16 deletions website/docs/r/eks_addon.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,15 @@ resource "aws_eks_addon" "example" {
}
```

## Example Update add-on usage with resolve_conflicts and PRESERVE
`resolve_conflicts` with `PRESERVE` can be used to retain the config changes applied to the add-on with kubectl while upgrading to a newer version of the add-on.

~> **Note:** `resolve_conflicts` with `PRESERVE` can only be used for upgrading the add-ons but not during the creation of add-on.
## Example Update add-on usage with resolve_conflicts_on_update and PRESERVE
`resolve_conflicts_on_update` with `PRESERVE` can be used to retain the config changes applied to the add-on with kubectl while upgrading to a newer version of the add-on.

```terraform
resource "aws_eks_addon" "example" {
cluster_name = aws_eks_cluster.example.name
addon_name = "coredns"
addon_version = "v1.8.7-eksbuild.3" #e.g., previous version v1.8.7-eksbuild.2 and the new version is v1.8.7-eksbuild.3
resolve_conflicts = "PRESERVE"
cluster_name = aws_eks_cluster.example.name
addon_name = "coredns"
addon_version = "v1.8.7-eksbuild.3" #e.g., previous version v1.8.7-eksbuild.2 and the new version is v1.8.7-eksbuild.3
resolve_conflicts_on_update = "PRESERVE"
}
```

Expand All @@ -56,11 +54,24 @@ Example to create a `coredns` managed addon with custom `configuration_values`.

```terraform
resource "aws_eks_addon" "example" {
cluster_name = "mycluster"
addon_name = "coredns"
addon_version = "v1.8.7-eksbuild.3"
resolve_conflicts = "OVERWRITE"
configuration_values = "{\"replicaCount\":4,\"resources\":{\"limits\":{\"cpu\":\"100m\",\"memory\":\"150Mi\"},\"requests\":{\"cpu\":\"100m\",\"memory\":\"150Mi\"}}}"
cluster_name = "mycluster"
addon_name = "coredns"
addon_version = "v1.8.7-eksbuild.3"
resolve_conflicts_on_create = "OVERWRITE"
configuration_values = jsonencode({
replicaCount = 4
resources = {
limits = {
cpu = "100m"
memory = "150Mi"
}
requests = {
cpu = "100m"
memory = "150Mi"
}
}
})
}
```

Expand Down Expand Up @@ -123,9 +134,9 @@ The following arguments are optional:
* `addon_version` – (Optional) The version of the EKS add-on. The version must
match one of the versions returned by [describe-addon-versions](https://docs.aws.amazon.com/cli/latest/reference/eks/describe-addon-versions.html).
* `configuration_values` - (Optional) custom configuration values for addons with single JSON string. This JSON string value must match the JSON schema derived from [describe-addon-configuration](https://docs.aws.amazon.com/cli/latest/reference/eks/describe-addon-configuration.html).
* `resolve_conflicts` - (Optional) Define how to resolve parameter value conflicts
when migrating an existing add-on to an Amazon EKS add-on or when applying
version updates to the add-on. Valid values are `NONE`, `OVERWRITE` and `PRESERVE`. For more details check [UpdateAddon](https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateAddon.html) API Docs.
* `resolve_conflicts_on_create` - (Optional) How to resolve field value conflicts when migrating a self-managed add-on to an Amazon EKS add-on. Valid values are `NONE` and `OVERWRITE`. For more details see the [CreateAddon](https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateAddon.html) API Docs.
* `resolve_conflicts_on_update` - (Optional) How to resolve field value conflicts for an Amazon EKS add-on if you've changed a value from the Amazon EKS default value. Valid values are `NONE` and `OVERWRITE`. For more details see the [UpdateAddon](https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateAddon.html) API Docs.
* `resolve_conflicts` - (**Deprecated** use the `resolve_conflicts_on_create` and `resolve_conflicts_on_update` attributes instead) Define how to resolve parameter value conflicts when migrating an existing add-on to an Amazon EKS add-on or when applying version updates to the add-on. Valid values are `NONE`, `OVERWRITE` and `PRESERVE`. Note that `PRESERVE` is only valid on addon update, not for initial addon creation. If you need to set this to `PRESERVE`, use the `resolve_conflicts_on_create` and `resolve_conflicts_on_update` attributes instead. For more details check [UpdateAddon](https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateAddon.html) API Docs.
* `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.
* `preserve` - (Optional) Indicates if you want to preserve the created resources when deleting the EKS add-on.
* `service_account_role_arn` - (Optional) The Amazon Resource Name (ARN) of an
Expand Down

0 comments on commit ac087fc

Please sign in to comment.