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

Allow !replace-ing service log-targets in merge #221

Closed
wants to merge 4 commits into from

Conversation

barrettj12
Copy link
Contributor

@barrettj12 barrettj12 commented May 18, 2023

Alternative to #223.

Context

#209 and #217 have included extensive discussion of the configuration and merging of log targets specified in a service definition. Two issues have been identified when it comes to merging the log-targets field:

  1. It is hard to restore the default behaviour provided when log-targets is not specified. The issue is that specifying a null value

    svc1:
      command: foo
      log-targets: ~ # or null

    parses identically to not specifying a value at all:

    svc1:
      command: foo
  2. It is hard to remove a log target which was previously specified. If your base layer contains

    svc1:
      log-targets: [a,b]

    and you merge the following layer on top of it:

    svc1:
      log-targets: [c]
      override: merge

    it will yield log-targets: [a,b,c].

As it stands, the only way to get around either issue is to replace the entire service - which is a real usability issue. This PR proposes one solution to the problem.

The solution

To solve (1), we need an explicit value to represent the default behaviour. We can't use null in a merge, as when this is parsed, it is indistinguishable from an unspecified value. To this end, I have added a default keyword which can be specified as the value of log-targets to restore the default behaviour:

svc1:
  log-targets: default

To solve the issue raised by Gustavo here, I have also added a none keyword which a service can use to entirely opt-out of log forwarding. Personally I feel this is a safer approach than what I've proposed in #217. Distinguishing between []string(nil) and []string{} in Go is fiddly and error-prone, and it's bound to cause issues down the road when merging and passing structs around.

Finally, I've added an all keyword - this is not strictly necessary, but could be convenient if a user has a large number of log targets.

To solve (2), I've added a !replace tag, which a service can use during a merge to indicate that the value of log-targets should be replaced, not merged. i.e. merging

svc1:
  log-targets: !replace [c]
  override: merge

on top of another layer will overwrite the value of log-targets, yielding just log-targets: [c].

So, the full schema for the log-targets field is now:

log-targets: [!replace] default | none | all | <list of log targets>

I've implemented a custom type LogTargets with a custom UnmarshalYAML method to handle all this.

Merging rules

These are the rules I decided on for merging log-targets - see the MergeLogTargets function. Open to discussing the details here.

  1. Merging anything1 <- !replace anything2 yields anything2. In particular, merging list1 <- !replace list2 yields list2.
  2. Merging list1 <- list2 will combine the two lists.
  3. Merging list <- keyword yields keyword.
  4. Merging keyword1 <- keyword2 yields keyword2
  5. Merging keyword <- list yields list (if the list is nonempty).

Essentially, the !replace directive is only needed when wanting to replace a list with another list.

Copy link
Contributor

@benhoyt benhoyt left a comment

Choose a reason for hiding this comment

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

I like this overall, and "all" and "none" seem potentially useful. Small suggestion about the Merge and Copy signatures, and recommendation that we only allow !replace with a list.

internal/plan/plan.go Outdated Show resolved Hide resolved
internal/plan/plan.go Outdated Show resolved Hide resolved
internal/plan/plan.go Show resolved Hide resolved
@barrettj12 barrettj12 changed the title Allow replacing service log-targets in merge Allow !replace-ing service log-targets in merge May 19, 2023
- change MergeLogTargets to (*LogTargets).Merge
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.

2 participants