Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added recording_mode{} attribute #87

Merged
merged 6 commits into from
Feb 27, 2024

Conversation

AdamTylerLynch
Copy link
Contributor

@AdamTylerLynch AdamTylerLynch commented Feb 23, 2024

what

Added recording_mode block.

Requesting maintainer guidance on properly defining the inputs as a practitioner would expect. The way it is defined now feels odd, requiring a variable assignment and then a list for recording_mode_override.

Example:

##---------------------------------------------------
## AWS Config to monitor compliance
##---------------------------------------------------
module "config" {
  source    = "cloudposse/terraform-aws-config/aws"
  name      = "${local.name}-config-${data.aws_caller_identity.current.account_id}"
  namespace = local.namespace

  s3_bucket_id                     = module.log_storage.bucket_id
  s3_bucket_arn                    = module.log_storage.bucket_arn
  global_resource_collector_region = data.aws_region.current.name

  create_iam_role = true

  recording_mode = {
    recording_frequency = "DAILY"
    recording_mode_override = {
      description         = "Override for specific resource types"
      recording_frequency = "CONTINUOUS"
      resource_types      = ["AWS::EC2::Instance"]
    }
  }
}

why

This feature allows for cost optimization. Adds the ability to leverage Periodic recording VS continious.

references

Gowiem
Gowiem previously requested changes Feb 24, 2024
Copy link
Member

@Gowiem Gowiem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, but I think we should change that type def unless I'm mistaken.

One other thing: We'll need to require the latest provider to support this, so we'll need to change to version = ">= 5.38" here.

Check out those updates and let me know your thoughts! Once you've got it into a solid spot where it's ready for another review, please do the following locally, adding + committing the result, and push to your branch:

make init
make readme

Thanks!

variables.tf Outdated
Comment on lines 150 to 151
- Continuous
- Daily
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provider docs seem to uppercase these, so just in case that is an issue..

Suggested change
- Continuous
- Daily
- CONTINUOUS
- DAILY

variables.tf Outdated
Comment on lines 159 to 163
recording_mode_override = optional(list(object({
description = string
recording_frequency = string
resource_types = list(string)
})))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT, it seems there can only be one recording_mode_override block, yeah? Considering that, I'd just make this a single option object like so:

Suggested change
recording_mode_override = optional(list(object({
description = string
recording_frequency = string
resource_types = list(string)
})))
recording_mode_override = optional(object({
description = string
recording_frequency = string
resource_types = list(string)
}))

This way we don't need to worry about list access and can avoid that data type. Or am I missing something on that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AWS API has a list, which means it is meant for future expansion. Whomever designed the Terraform resource did not realize that and just coded a structure.

We can align to the Terraform resource, knowing that in the future this could be an issue.

main.tf Show resolved Hide resolved
variables.tf Outdated
@@ -144,6 +144,27 @@ variable "managed_rules" {
default = {}
}

variable "recording_mode" {
description = <<-DOC
The mode for AWS Config to record configuration changes. Possible values are:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could create a validation block for these values in this variable, but not required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding validation client side means we need to publish new versions as the API changes. My preference is to provide clear examples, optional attributes, and let the APIs do the validation. But, I am open to adding it if you feel it's necessary.

@AdamTylerLynch AdamTylerLynch changed the title added recording_mode{} [WIP] added recording_mode{} Feb 24, 2024
@AdamTylerLynch
Copy link
Contributor Author

AdamTylerLynch commented Feb 24, 2024

Output post apply:

Terraform will perform the following actions:

  # module.config.aws_config_configuration_recorder.recorder[0] will be updated in-place
  ~ resource "aws_config_configuration_recorder" "recorder" {
        id       = "ga-account-guardian-config-123456789123-config"
        name     = "ga-account-guardian-config-123456789123-config"
        # (1 unchanged attribute hidden)

      ~ recording_mode {
            # (1 unchanged attribute hidden)

          + recording_mode_override {
              + description         = "Override for specific resource types"
              + recording_frequency = "CONTINUOUS"
              + resource_types      = [
                  + "AWS::EC2::Instance",
                ]
            }
        }

        # (1 unchanged block hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
module.config.aws_config_configuration_recorder.recorder[0]: Modifying... [id=ga-account-guardian-config-123456789123-config]
module.config.aws_config_configuration_recorder.recorder[0]: Modifications complete after 0s [id=ga-account-guardian-config-123456789123-config]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Outputs:


@AdamTylerLynch AdamTylerLynch changed the title [WIP] added recording_mode{} added recording_mode{} attribute Feb 24, 2024
@Gowiem
Copy link
Member

Gowiem commented Feb 24, 2024

/terratest

@Gowiem
Copy link
Member

Gowiem commented Feb 26, 2024

@AdamTylerLynch Tests are failing elsewhere (#86), so we're working on that internally and will circle back once they're fixed 👍 Thanks for the patience!

@Nuru
Copy link
Contributor

Nuru commented Feb 27, 2024

/terratest

Copy link
Contributor

@Nuru Nuru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you! There remains a lot of cruft in this module to clean up around testing and examples, but that is beyond the scope of this PR.

@Nuru Nuru dismissed Gowiem’s stale review February 27, 2024 21:37

Requested changes have been made

@Nuru
Copy link
Contributor

Nuru commented Feb 27, 2024

/terratest

@Nuru
Copy link
Contributor

Nuru commented Feb 28, 2024

@AdamTylerLynch Thank you very much for this PR. As you can see, it elegantly resolved a number of piecemeal attempts at adding this feature and complaints about missing support.

@Gowiem Thank you for all your help. Your guidance was excellent, so by the time I got to look at this PR, all my concerns about the original PR had been addressed.

FYI, regarding list vs. not a list inputs, this is a complex issue about which I'm going to write a more detailed article. As a general rule, if the Terraform resource block is documented in the Terraform resource to be a list (see, for example, aws_route_table.route), we model it as a list, even if it is documented as a list of max length 1. If it is documented as an optional block, as here with recording_mode, we model it as an optional object.

Now if the variable in question is involved with determining the number of resources to create, a number which must be known at plan time, we always use a list or map. But in this case where, even if the API is documented as a list, the Terraform resource is not documented as being a block list, we leave it an object.

Regarding validation blocks, we typically use them as enhanced documentation for the case where the input type does not match the resource attribute type. The primary case being these variables that control the number of resources. We may take an optional value as a list of length zero or one, even though the resource takes a plain value, so there we add a validation rejecting lists longer than length one and explaining the situation. Other situation for custom validation are where there is some value (typically one or more of a set of enums) we do not support, or where an input is removed but we want to provide guidance on how to migrate to its replacement (in which case anything but the default value triggers an error message).

I agree with @AdamTylerLynch that duplicating validation done by the API adds maintenance burden and slows the adoption of new features without providing enough benefit to be worth it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants