atmos icon indicating copy to clipboard operation
atmos copied to clipboard

feat: add !unset YAML function to delete keys from configuration

Open osterman opened this issue 5 months ago β€’ 14 comments

what

  • Add new !unset YAML function that completely removes keys from configuration during inheritance and merging
  • Implement processing in both stack merging (yaml_func_utils.go) and config loading (process_yaml.go)
  • Add comprehensive unit tests for all functionality
  • Create documentation with examples and use cases
  • Update YAML functions index documentation

why

  • Users need a way to explicitly remove inherited configuration values, not just override them with null
  • Current workarounds require physically removing or commenting out keys in parent configurations
  • This addresses GitHub issue #227: "A YAML way of undefining a value without removing the key"
  • Provides fine-grained control over configuration inheritance in complex stack hierarchies

Key Features

  • Complete removal: Unlike setting to null, !unset completely removes the key from configuration
  • Inheritance control: Child configurations can remove values inherited from parents
  • Works everywhere: Functions in all Atmos configuration sections (vars, settings, env, metadata, etc.)
  • Type-safe: Operates after YAML parsing, ensuring no syntax breakage
  • Respects skip list: Can be disabled via skip list if needed

Examples

Basic Usage

# parent.yaml
components:
  terraform:
    vpc:
      vars:
        enable_nat_gateway: true
        enable_vpn_gateway: true

# child.yaml
import:
  - parent

components:
  terraform:
    vpc:
      vars:
        enable_vpn_gateway: !unset  # Completely removes this key

Removing Nested Values

config:
  database:
    host: "prod.db.example.com"
    backup_enabled: true

# Override:
config:
  database:
    backup_enabled: !unset  # Remove backup config
    host: "dev.db.example.com"

Testing

All tests pass:

  • βœ… Unit tests for config processing
  • βœ… Unit tests for stack processing
  • βœ… Integration tests with other YAML functions
  • βœ… Skip list functionality tests
  • βœ… Inheritance scenario tests

references

  • Closes #227
  • Related to #267 (YAML Explicit Typing support)

πŸ€– Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a YAML !unset function to remove keys or list items during config processing and inheritance. Works at any depth, supports multiple unsets, and coexists with other YAML functions.
  • Tests
    • Introduced comprehensive tests covering flat and nested structures, arrays, multiple/nested unsets, inheritance scenarios, and edge cases.
  • Documentation
    • Added dedicated docs and examples for !unset, including usage in stack manifests, nested removals, list handling, and guidance on expected behavior.

osterman avatar Sep 25 '25 17:09 osterman

[!WARNING]

Rate limit exceeded

@osterman has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 23 minutes and 28 seconds before requesting another review.

βŒ› How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 3728a05733708c7a3476b405733e8205ffa3f0d9 and 4626beb90a1c5da3636a8e8e8ec164dcf1a29221.

πŸ“’ Files selected for processing (8)
  • internal/exec/yaml_func_unset_test.go (1 hunks)
  • pkg/config/load_config_test.go (1 hunks)
  • pkg/config/process_yaml.go (3 hunks)
  • pkg/config/process_yaml_unset_test.go (1 hunks)
  • pkg/utils/array_cleanup.go (1 hunks)
  • pkg/utils/array_cleanup_test.go (1 hunks)
  • pkg/utils/yaml_utils.go (4 hunks)
  • website/docs/functions/yaml/unset.mdx (1 hunks)
πŸ“ Walkthrough

Walkthrough

Adds a new !unset YAML function and supporting logic to mark and remove values during YAML processing. Implements UnsetMarker propagation across maps/sequences, updates processing flow for scalar/mapping handling, adds tests validating unset behavior in various scenarios, and documents the feature.

Changes

Cohort / File(s) Summary
YAML unset core implementation
internal/exec/yaml_func_utils.go, pkg/utils/yaml_utils.go, pkg/config/process_yaml.go
Introduces UnsetMarker type and !unset tag constant; extends node processing (mapping/scalar/sequence) to detect and propagate unset markers; updates scalar dispatch to remove keys on !unset; integrates tag into recognized YAML functions.
Unit tests for unset
internal/exec/yaml_func_unset_test.go, pkg/config/process_yaml_unset_test.go
Adds comprehensive tests covering flat/nested maps, arrays, multiple/nested unsets, skip-lists, interactions with other tags, inheritance-like scenarios, empty/invalid cases, and overall preprocessing behavior.
Documentation
website/docs/functions/yaml/index.mdx, website/docs/functions/yaml/unset.mdx
Documents the new !unset YAML function with overview, usage examples, detailed behavior, use cases, and references; updates function index.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User YAML
  participant L as YAML Loader
  participant P as processYaml
  participant M as processMappingNode / processChildren
  participant S as processScalarNode
  participant C as processCustomTags
  participant U$ as UnsetMarker
  participant V as Viper Store

  U->>L: Provide YAML with !unset
  L->>P: Parse AST Node
  alt Mapping/Sequence
    P->>M: Traverse keys/items
    loop For each key/item
      M->>S: Process value node
      S->>C: Check custom tag
      alt tag == !unset
        C-->>S: Return UnsetMarker
        S-->>M: Propagate UnsetMarker
        M-->>V: Skip set/remove key/item
      else other/regular tag
        C-->>S: Resolved value
        S-->>M: Value
        M-->>V: Set value
      end
    end
  else Scalar (top-level)
    P->>S: Process scalar
    S->>C: Check tag
    alt tag == !unset
      C-->>S: UnsetMarker
      S-->>V: Remove key at path
    else regular
      C-->>S: Resolved value
      S-->>V: Set value
    end
  end

  note over U$,V: UnsetMarker is a signal to delete/omit<br/>without storing a concrete value.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

minor

Suggested reviewers

  • aknysh

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
βœ… Passed checks (4 passed)
Check name Status Explanation
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check βœ… Passed The title clearly and concisely describes the introduction of the !unset YAML function for deleting keys, matching the primary change in the pull request.
Linked Issues Check βœ… Passed The pull request implements the sentinel !unset tag, propagates an UnsetMarker through processing, removes keys during merging and config loading, and includes tests verifying inheritance and omission behaviors as specified in issue #227.
Out of Scope Changes Check βœ… Passed All modifications relate directly to supporting the new !unset YAML function through implementation, testing, or documentation, with no unrelated changes detected.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot] avatar Sep 25 '25 17:09 coderabbitai[bot]

[!WARNING]

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues. Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

mergify[bot] avatar Sep 26 '25 05:09 mergify[bot]

πŸ’₯ This pull request now has conflicts. Could you fix it @osterman? πŸ™

mergify[bot] avatar Oct 02 '25 13:10 mergify[bot]

[!WARNING]

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-01-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

github-actions[bot] avatar Dec 01 '25 19:12 github-actions[bot]

[!WARNING]

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-06-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

github-actions[bot] avatar Dec 01 '25 19:12 github-actions[bot]

πŸ’₯ This pull request now has conflicts. Could you fix it @osterman? πŸ™

mergify[bot] avatar Dec 06 '25 19:12 mergify[bot]

[!WARNING]

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-09-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

github-actions[bot] avatar Dec 06 '25 20:12 github-actions[bot]

πŸ’₯ This pull request now has conflicts. Could you fix it @osterman? πŸ™

mergify[bot] avatar Dec 09 '25 04:12 mergify[bot]

[!WARNING]

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-09-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

github-actions[bot] avatar Dec 09 '25 04:12 github-actions[bot]

πŸ’₯ This pull request now has conflicts. Could you fix it @osterman? πŸ™

mergify[bot] avatar Dec 09 '25 05:12 mergify[bot]

[!WARNING]

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-09-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

github-actions[bot] avatar Dec 09 '25 15:12 github-actions[bot]

[!WARNING]

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-10-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

github-actions[bot] avatar Dec 09 '25 19:12 github-actions[bot]

Codecov Report

:x: Patch coverage is 74.48276% with 37 lines in your changes missing coverage. Please review. :white_check_mark: Project coverage is 73.13%. Comparing base (448d405) to head (164f6e2).

Files with missing lines Patch % Lines
pkg/config/process_yaml.go 52.00% 15 Missing and 9 partials :warning:
internal/exec/yaml_func_utils.go 72.72% 3 Missing and 3 partials :warning:
pkg/utils/array_cleanup.go 91.54% 4 Missing and 2 partials :warning:
pkg/utils/yaml_utils.go 50.00% 0 Missing and 1 partial :warning:

:x: Your patch check has failed because the patch coverage (74.48%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1521      +/-   ##
==========================================
+ Coverage   73.11%   73.13%   +0.01%     
==========================================
  Files         550      551       +1     
  Lines       53168    53307     +139     
==========================================
+ Hits        38873    38984     +111     
- Misses      11439    11454      +15     
- Partials     2856     2869      +13     
Flag Coverage Ξ”
unittests 73.13% <74.48%> (+0.01%) :arrow_up:

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Ξ”
pkg/utils/yaml_utils.go 81.15% <50.00%> (+0.05%) :arrow_up:
internal/exec/yaml_func_utils.go 87.71% <72.72%> (-1.98%) :arrow_down:
pkg/utils/array_cleanup.go 91.54% <91.54%> (ΓΈ)
pkg/config/process_yaml.go 67.15% <52.00%> (-2.05%) :arrow_down:

... and 2 files with indirect coverage changes

:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

codecov[bot] avatar Dec 09 '25 19:12 codecov[bot]

[!WARNING]

Changelog Entry Required

This PR is labeled minor or major but doesn't include a changelog entry.

Action needed: Add a new blog post in website/blog/ to announce this change.

Example filename: website/blog/2025-12-18-feature-name.mdx

Alternatively: If this change doesn't require a changelog entry, remove the minor or major label.

github-actions[bot] avatar Dec 10 '25 02:12 github-actions[bot]

Dependency Review

βœ… No vulnerabilities or license issues found.

Scanned Files

None

github-actions[bot] avatar Dec 18 '25 18:12 github-actions[bot]