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

feat: new configuration system, config subcommand #736

Merged
merged 38 commits into from
Jun 6, 2024
Merged

Conversation

phm07
Copy link
Contributor

@phm07 phm07 commented Apr 19, 2024

This PR implements the new configuration system as described in #762.

Closes #762
In preparation for #434

Copy link

codecov bot commented Apr 19, 2024

Codecov Report

Attention: Patch coverage is 46.91011% with 378 lines in your changes missing coverage. Please review.

Project coverage is 59.32%. Comparing base (fa9b366) to head (77aa0d4).

Files Patch % Lines
internal/state/config/config.go 0.00% 124 Missing ⚠️
internal/state/config/options.go 10.83% 107 Missing ⚠️
internal/cmd/config/config.go 0.00% 42 Missing ⚠️
internal/state/config/context.go 0.00% 29 Missing ⚠️
internal/state/config/preferences.go 74.64% 15 Missing and 3 partials ⚠️
internal/state/state.go 0.00% 11 Missing ⚠️
internal/cmd/config/add.go 80.85% 5 Missing and 4 partials ⚠️
internal/cmd/config/remove.go 81.25% 4 Missing and 5 partials ⚠️
internal/cmd/config/util.go 72.00% 6 Missing and 1 partial ⚠️
internal/cmd/config/list.go 90.38% 3 Missing and 2 partials ⚠️
... and 6 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #736      +/-   ##
==========================================
- Coverage   60.36%   59.32%   -1.04%     
==========================================
  Files         189      203      +14     
  Lines        6776     7460     +684     
==========================================
+ Hits         4090     4426     +336     
- Misses       2072     2400     +328     
- Partials      614      634      +20     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@phm07 phm07 force-pushed the configuration branch 3 times, most recently from f895daf to 8b2856d Compare May 2, 2024 12:33
internal/cmd/cmpl/suggestions.go Show resolved Hide resolved
internal/cmd/firewall/describe.go Outdated Show resolved Hide resolved
Copy link
Member

@jooola jooola left a comment

Choose a reason for hiding this comment

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

Overall, I like how it is structured.

I think a few refactoring passes are needed before this can be merged.

I also noticed that the viper library already ships our previous toml library, so might be shipping both. Are we ok with the binary size?

internal/cmd/config/config.go Outdated Show resolved Hide resolved
internal/cmd/config/helptext/generate.go Show resolved Hide resolved
internal/cmd/config/list.go Outdated Show resolved Hide resolved
internal/state/config/config.go Show resolved Hide resolved
internal/state/config/options.go Show resolved Hide resolved
@phm07
Copy link
Contributor Author

phm07 commented May 10, 2024

I also noticed that the viper library already ships our previous toml library, so might be shipping both. Are we ok with the binary size?

I'll put the toml library change into another PR and then we can compare binary sizes. I don't think it's a huge difference.

Edit: See #758

@phm07 phm07 force-pushed the configuration branch 3 times, most recently from dd2eda9 to 69096d4 Compare May 23, 2024 12:29
@phm07 phm07 changed the title feat: add global/per-context configuration preferences, add config command feat: new configuration system, config subcommand May 23, 2024
@phm07 phm07 self-assigned this May 23, 2024
@phm07 phm07 added the feature label May 23, 2024
@phm07 phm07 marked this pull request as ready for review May 23, 2024 12:31
@phm07 phm07 requested a review from a team as a code owner May 23, 2024 12:31
Copy link
Member

@apricote apricote left a comment

Choose a reason for hiding this comment

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

Partial review (its a huge PR ;) ), will continue tomorrow :)

internal/cmd/firewall/add_rule.go Outdated Show resolved Hide resolved
internal/cmd/firewall/delete_rule.go Outdated Show resolved Hide resolved
internal/cmd/firewall/describe.go Outdated Show resolved Hide resolved
internal/cmd/firewall/describe_test.go Outdated Show resolved Hide resolved
internal/cmd/util/util.go Show resolved Hide resolved
internal/state/state.go Show resolved Hide resolved
internal/state/state.go Outdated Show resolved Hide resolved
@phm07
Copy link
Contributor Author

phm07 commented Jun 5, 2024

Do you think it would be possible to add the config.OptionQuiet options inside the config struct? This way we would only have the config struct in the state and get the value from it?

So instead of config.OptionQuiet.Get(s.Config()) we would simply have s.Config().Quiet() ?

This would technically be possible, but has a lot of drawbacks:

  • There would be a lot of code duplication. There would need to be a method implemented on the config struct for every single option. Also there would need to be a map that stores all option. There is no way to create such a map automatically when getter methods are used to access options. Right now newOpt is used to handle that.
  • Testing would be a lot harder since options would be hard coded. Currently, the option set is extended for some tests. This is for example used to test nested options which don't exist yet.
  • It would unnecessarily clutter the Config interface.

I considered the approach you described while implementing the spec, however the current approach offers way more concise code (it only takes a call of the newOpt function to create a new option) and the only trade-off is that the code is slightly less pretty.

Other than that, there is a bunch of code that can be deduplicated, extracted in smaller functions, so the higher level logic is easier to understand.

Feel free to comment those parts in your review.

@jooola
Copy link
Member

jooola commented Jun 5, 2024

There would be a lot of code duplication. There would need to be a method implemented on the config struct for every single option. Also there would need to be a map that stores all option. There is no way to create such a map automatically when getter methods are used to access options. Right now newOpt is used to handle that.

I don't think it increases the duplication too much, it is moving some code around. Instead of having "complex" code in the business logic, we have dumb code in the config package (at least we have a dumb API, and hide the complexity).

Testing would be a lot harder since options would be hard coded. Currently, the option set is extended for some tests. This is for example used to test nested options which don't exist yet.

I am not sure if this is a real problem, we could have dedicated config struct for testing that embed the normal config struct.

It would unnecessarily clutter the Config interface.

I prefer to clutter the config interface instead of the business code. Ensuring a proper separation of concern with simple APIs, will make the project easier to work with.

Feel free to comment those parts in your review.

Will do.

@jooola
Copy link
Member

jooola commented Jun 5, 2024

There would be a lot of code duplication. There would need to be a method implemented on the config struct for every single option. Also there would need to be a map that stores all option. There is no way to create such a map automatically when getter methods are used to access options. Right now newOpt is used to handle that.

That said, I don't have a strong opinion. I just wanted to discuss the topic, to see if we can have an even better API.

Copy link
Member

@jooola jooola left a comment

Choose a reason for hiding this comment

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

This is getting better and better, I like it!

I added the few comment in places I though we could deduplicate/move some code.

internal/cmd/config/add.go Outdated Show resolved Hide resolved
internal/cmd/config/get.go Outdated Show resolved Hide resolved
internal/cmd/config/add.go Outdated Show resolved Hide resolved
internal/cmd/config/remove.go Outdated Show resolved Hide resolved
internal/cmd/config/remove.go Show resolved Hide resolved
internal/cmd/config/set.go Outdated Show resolved Hide resolved
internal/cmd/config/list.go Outdated Show resolved Hide resolved
internal/cmd/config/set.go Outdated Show resolved Hide resolved
@phm07
Copy link
Contributor Author

phm07 commented Jun 5, 2024

I don't think it increases the duplication too much, it is moving some code around. Instead of having "complex" code in the business logic, we have dumb code in the config package (at least we have a dumb API, and hide the complexity).

In the current implementation you need:

  • One variable declaration using the newOpt method and you're done. Everything else is done for you.

If options were implemented on the config interface, you would need:

  • Some sort of variable declaration for the option, since it would need to be re-used multiple times (see below)
  • A function declaration for the getter on the Config interface
  • An implementation of the getter method for each struct that implements the Config interface (variable would be needed here)
  • Some piece of code that adds the option to a global map which contains all options (needed so that options can be iterated over and can be retrieved by name; variable would be needed here too)

This is tedious and would definitely need to be documented somewhere. Also it could be easy to forget some steps, especially for someone in the future who didn't read this PR.

I am not sure if this is a real problem, we could have dedicated config struct for testing that embed the normal config struct.

I'm not sure if I understand you correctly here, but that's not how structs work in Go. You'd need an interface to abstract everything away (which would mean even more code duplication)

I prefer to clutter the config interface instead of the business code. Ensuring a proper separation of concern with simple APIs, will make the project easier to work with.

Fair point, but I don't think config.Option<...>.Get(s.Config()) is clutter. config.Option<...> allows you to autocomplete all valid options and config.OptionX.<...> lets you autocomplete all functions than can be performed on options, like overriding them, getting values or getting the type. Making it so that it accepts a config.Config makes it easily mockable.

That said, I don't have a strong opinion. I just wanted to discuss the topic, to see if we can have an even better API.

That's completely valid. As I said, I first followed the approach you proposed too when implementing the spec, but it really didn't make that much sense. It might have a prettier outer-facing API, but remember that we have to maintain the actual implementation as well.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
internal/cmd/config/util.go Show resolved Hide resolved
@jooola
Copy link
Member

jooola commented Jun 5, 2024

config.OptionQuiet.Get(s.Config()) => s.Config().Quiet()

Alright, case close from my side then.

@phm07 phm07 force-pushed the configuration branch 2 times, most recently from acd7fb5 to bf5e964 Compare June 6, 2024 11:53
Copy link
Member

@apricote apricote left a comment

Choose a reason for hiding this comment

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

Awesome! Looking really good now :)

(We will for sure find some bugs and rough edges after merging, but that happens always).

@phm07 phm07 merged commit d1c6678 into main Jun 6, 2024
5 checks passed
@phm07 phm07 deleted the configuration branch June 6, 2024 14:52
phm07 added a commit that referenced this pull request Jun 6, 2024
This PR adds tests to the `context` subcommands using the new
configuration system implemented in #736
phm07 added a commit that referenced this pull request Jun 20, 2024
When a `*pflag.FlagSet` is parsed, it outputs a usage string if the
`--help` flag is included. Since Cobra already does this, this behavior
needs to be disabled or the usage will be printed twice.

---

Since #736 hasn't been release yet, this fix shouldn't appear in the
changelog.

BEGIN_COMMIT_OVERRIDE
feat: new configuration system, config subcommand 
END_COMMIT_OVERRIDE
phm07 pushed a commit that referenced this pull request Jun 20, 2024
🤖 I have created a release *beep* *boop*
---


##
[1.44.0](v1.43.1...v1.44.0)
(2024-06-20)


### Features

* delete multiple resources in parallel
([#761](#761))
([f2fb321](f2fb321))
* improve toml formatting
([#758](#758))
([eacb7dd](eacb7dd))
* **load-balancer:** allow specifying health check options in
add-service ([#743](#743))
([2cd08b2](2cd08b2)),
closes [#742](#742)
* new action waiting progress
([#749](#749))
([9e30f3f](9e30f3f))
* new configuration system, config subcommand
([#736](#736))
([d1c6678](d1c6678))
* **server-type:** add deprecated column to list command
([#780](#780))
([906f864](906f864))
* **server:** add default-ssh-keys option
([#759](#759))
([9b34d26](9b34d26))


### Bug Fixes

* **firewall:** 'create --rules-file' not working with outbound rules
([#752](#752))
([2f2be32](2f2be32)),
closes [#750](#750)
* network list server count format
([#783](#783))
([f69d261](f69d261))
* track progress if the terminal width allows it
([#768](#768))
([069fffe](069fffe)),
closes [#767](#767)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Design Doc] feat: new configuration system + config subcommand
3 participants