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

*: Refactor codebase with linters/formatters and upstream patterns #1253

Merged
merged 17 commits into from
Oct 17, 2023

Conversation

saswatamcode
Copy link
Member

@saswatamcode saswatamcode commented Oct 11, 2023

Lots of TODOs still pending (that will be done in separate PRs), but this does the following.

  • Bump prom client, and add rules to use similar upstream patterns for instrumentation
  • Deprecate ioutil
  • Make all errors consistent and move completely to github.com/efficientgo/core/errors
  • Add bingo and several linters/formatters
  • Deprecate fake.NewClient
  • Fix a bunch of lint problems (although many still exist within tests)

@openshift-ci
Copy link

openshift-ci bot commented Oct 11, 2023

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@saswatamcode
Copy link
Member Author

saswatamcode commented Oct 12, 2023

/test test-unit

@openshift-ci
Copy link

openshift-ci bot commented Oct 12, 2023

@saswatamcode: The /retest command does not accept any targets.
The following commands are available to trigger required jobs:

  • /test e2e-kind
  • /test images
  • /test ocm-ci-rbac
  • /test pr-image-mirror-endpoint-monitoring-operator
  • /test pr-image-mirror-grafana-dashboard-loader
  • /test pr-image-mirror-metrics-collector
  • /test pr-image-mirror-multicluster-observability-operator
  • /test pr-image-mirror-rbac-query-proxy
  • /test sonarcloud
  • /test test-e2e
  • /test test-unit

Use /test all to run all jobs.

In response to this:

/retest tests-unit

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@saswatamcode
Copy link
Member Author

/test test-unit

@saswatamcode saswatamcode self-assigned this Oct 12, 2023
@saswatamcode
Copy link
Member Author

/retest

worker, err := forwarder.New(*cfg)
if err != nil {
return fmt.Errorf("failed to configure metrics collector: %v", err)
return errors.Wrap(err, "failed to configure metrics collector")
Copy link
Contributor

Choose a reason for hiding this comment

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

any particular reason we would choose to import this package to handle errors in favour of stdlib?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's what we use for thanos upstream (or aiming to, promql-engine already uses it). This returns the stacktrace which is super useful at times. github.com/pkg/errors did similar I think, but is no longer maintained.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also prefer using the stdlib with fmt.Errorf("%w"). Regarding the stack trace, I don't see why we would need it. I mean, if so, it is a symptom of bad error handling that is not descriptive enough in the stack.
I don't like depending on those small libs while the stdlib does the job. But it's me 😉

curl -L https://github.com/operator-framework/operator-sdk/releases/download/${_OPERATOR_SDK_VERSION}/operator-sdk_linux_amd64 -o operator-sdk
elif [[ $OSTYPE == "darwin"* ]]; then
curl -L https://github.com/operator-framework/operator-sdk/releases/download/${_OPERATOR_SDK_VERSION}/operator-sdk_darwin_amd64 -o operator-sdk
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

could probably make this a one liner with some uname command as a subshell?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup! Just fyi, these shellscript changes are from formatting, not explicit changes

Copy link
Contributor

Choose a reason for hiding this comment

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

yep, i get that, just flagging as I go but will pause on that and we can tackle bash maybe in isolation in a follow up

Copy link
Contributor

Choose a reason for hiding this comment

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

Future note: we need to parameterize the architecture here too. Not everyone is running amd64. Me and all other darwin users in the team are running arm64.

type RuleMatcher interface {
MatchRules() []string
}

func init() {
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Name: "federate_filtered_samples",
Help: "Tracks the number of samples filtered per federation",
}),
gaugeFederateErrors: promauto.With(cfg.Registry).NewGauge(prometheus.GaugeOpts{
Copy link
Contributor

Choose a reason for hiding this comment

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

should we add a metric to calc total also?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup, will add. I think there is also something else here that causes tests to fail, will take a look.

@@ -1,101 +0,0 @@
package http
Copy link
Contributor

Choose a reason for hiding this comment

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

was this unused?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, builds without it!

# this package has a binary, so:
command -v kubectl
if [ $? -ne 0 ]; then
echo "=====Setup kubectl====="
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe we could take some inspiration from https://github.com/rhobs/configuration/blob/main/Makefile#L216-L218 around handling this? seems cleaner?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, haven't gone through all the shellscripts yet. I might clean them up explicitly in another follow-up!

# kubectl are now installed in current dir
echo -n "kubectl version" && kubectl version
echo "=====Setup kubectl====="
# kubectl required for kind
Copy link
Contributor

Choose a reason for hiding this comment

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

this all looks repeated? maybe we can simplify

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup!

echo "Current directory"
echo $(pwd)
cd ${WORKDIR}/..
git clone https://github.com/coreos/kube-prometheus.git
Copy link
Contributor

Choose a reason for hiding this comment

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

url is outdated and will cause a redirect

echo $(pwd)
cd ${WORKDIR}/..
git clone https://github.com/coreos/kube-prometheus.git
echo "Replace namespace with openshift-monitoring"
Copy link
Contributor

Choose a reason for hiding this comment

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

im trying to understnad whats happening here? on KinD cluster, why do we need to use openshift-monitoring namespace with prom operator? 🤔

@thibaultmg
Copy link
Contributor

I reviewed the PR commit by commit. Thanks for having them well organised!
Changes look good to me. (did not review original code which I think we'll touch later)
I would avoid adding the new error package and bingo. But if everybody is used to them this is not a blocker at all.
Congrats for this huge cleaning!
Waiting for tests to pass

@saswatamcode
Copy link
Member Author

saswatamcode commented Oct 14, 2023

Errors

I would avoid adding the new error package

I understand the reason of not wanting to depend on small package, but there are a few reasons, why I think it is generally better than the combination of stdlib fmt.Errorf and errors.New,

  • Wrapping errors with fmt.Errorf needs a %w which is super easy to forget to do, and easy to miss in review. I think we can construct some linter rule for it using some custom lint tools (faillint, golangci-lint don't do this I think), but that's extra check to maintain. Due to the nature of such a single arg function, it is prone to inconsistent wrapping.
  • Relying on errors.New for new errors and then fmt.Errorf for wrapping doesn't look clean, and increases cognitive load. I'd rather prefer using single package consistently for everything.

Regarding the stack trace, I don't see why we would need it. I mean, if so, it is a symptom of bad error handling that is not descriptive enough in the stack.
I don't like depending on those small libs while the stdlib does the job.

  • I get what you're saying about non-descriptive errors @thibaultmg, but I'd argue stack traces aren't exactly to describe the error or "cause" of the error, but rather to highlight the specific code path that the error resulted from, which is extremely useful when debugging issues with complex codebases like this one. And stacktraces are useful enough that people even created o11y signal from it i.e profiling. I'd rather have stacktraces and not use it, rather than not have stacktraces but need it. 😅 Wdyt?

And if anything, we maintain efficientgo/core, so there isn't much worry about governance.

Bingo

and bingo

Curious about this, why do we want to avoid bingo? Is it the extra files or something else you noticed @thibaultmg?

Logging

Also, I have an outstanding question apart from errors, which is logging. Seems like this repo uses go-kit/log (which we use upstream quite a lot in Prometheus and Thanos), and klog which is the standard k8s logger, quite a lot. Also, Kubebuilder-based operators usually use zapr which is what obo uses. I'd like to move to one consistent logger. What do you think we should use here then? My personal pick would be go-kit/log as we can do multiple formats and filter via log level, and it's the one current team is most familiar with. But what do you think @thibaultmg @philipgough? 🙂

@saswatamcode saswatamcode force-pushed the lint-fmt branch 2 times, most recently from c635ee9 to 81c6df5 Compare October 15, 2023 12:54
@saswatamcode
Copy link
Member Author

/retest

@douglascamata douglascamata self-requested a review October 16, 2023 11:14
@douglascamata
Copy link
Contributor

On error handling, I heavily agree with @thibaultmg's point.

  • I do not think adding a %w is easy to forget and miss in review. In fact, it becomes instinct after a few uses. Some of us in the team might see it as easy to forget only because we lack experience with the standard library's error wrapping. It's a matter of getting acquainted with the habit (less things to keep inside our heads = cognitive_load--).
  • I don't think fmt.Errorf implies in extra cognitive load -- where would such load come from? It might not look clean for some, which is fair, but not a good reason to rely on a 3rd party library. In fact, we are better off using the Golang's standard library way, which can be improved over time. The Go team will take care of the backwards compatibility and migration for us.
  • Extra: by using the official error wrapping of Go, in the future we might get stacktraces for free and won't need a 3rd party package for this. To me it's fine to use a 3rd party package for stacktraces if they prove helpful. More than once I already caught myself with a stacktrace that didn't help me pinpoint the issue.

On Bingo, I also agree with @thibaultmg's point.

  • It's not about "why avoid Bingo?" it's about "why use Bingo if go install is enough"? Bingo comes from a time where go install didn't exist. Nowadays we have a proper solution from the Go team which they will evolve over time together with all the rest of the toolchain. It's much more likely that a Go developer already knows go install (less things to keep inside our heads = cognitive_load--) than Bingo.
  • It's not only about how many files Bingo adds to the project, but also how much maintenance is required to upgrade tooling (more things to keep inside our heads = cognitive_load++). Meanwhile, go install is just a few lines in a README, Makefile or Shell script -- to upgrade something I change the version number and that's all. Also note that the commands in Bingo and go install have slightly different syntax sometimes (more things to keep inside our heads = cognitive_load++).

Overall, my opinion is: I like to stick with the standard library whenever possible. We should all be very familiar with it. When not possible, let's look for tools that are "de-facto" standards in the community. There are many good reasons for this, including but not limited to:

  • By using the standard library and "de-facto" standard packages, we reduce onboarding time and cost of codebase because we will be using constructs that are familiar to every Go developer (less things to keep inside our heads = cognitive_load--). On the maintainership side, we don't have to create and maintain a package for this. The less code we have to maintain (less things to keep inside our heads = cognitive_load--), the more we can focus on what matters most.
  • We see that the standard library is constantly evolving, getting new features and incorporating feedback from people using it. The Go team has been doing a great job at this and keeping backwards compatibility. It's a bad idea to lock ourselves out of it or push the responsibility of adopting updates to the standard library to someone else.

@thibaultmg
Copy link
Contributor

Hey,

Relying on errors.New for new errors and then fmt.Errorf for wrapping doesn't look clean, and increases cognitive load. I'd rather prefer using single package consistently for everything.

I think it is more of a matter of what tools you are used to. Because for me, it is this errors.Wrap that increases the cognitive load. I have to check the package to understand why it's there.
Regarding the stack trace, this can be added when debugging with 3 lines of code. And it happens rarely. So adding a specific dependency for that doesn't seem worth it to me.

Curious about this, why do we want to avoid bingo? Is it the extra files or something else you noticed

I admit it brings useful things to the table. But I don't think we need it enough to not use go install. We could isolate these dev bins in a .bin dir in the package and have all tools consume these deps from here. The other useful things is the ability to selectively add deps. We could have one make target by dep. To me there are few things that bingo brings that cannot be done with standard tooling plus some small conventions.

Also, I have an outstanding question apart from errors, which is logging.

I don't have strong opinions on this. In my personal projects I use zerolog which I like. With go 1.21 I would give a shot to slog from the standard lib.

Overall I totally agree with @douglascamata remarks about the benefits of using the standard lib as much as possible. This is what I strive for in my projects. But again, It is not a blocker if the majority of the team enjoys these tools 😉

Copy link
Contributor

@thibaultmg thibaultmg left a comment

Choose a reason for hiding this comment

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

Looks Good! 🚀

Copy link
Contributor

@douglascamata douglascamata left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

@openshift-ci
Copy link

openshift-ci bot commented Oct 17, 2023

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: douglascamata, saswatamcode, thibaultmg

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:
  • OWNERS [douglascamata,saswatamcode]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
…h github.com/efficientgo/core/errors

Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
Signed-off-by: Saswata Mukherjee <[email protected]>
@openshift-ci
Copy link

openshift-ci bot commented Oct 17, 2023

New changes are detected. LGTM label has been removed.

@saswatamcode
Copy link
Member Author

/retest

@sonarqubecloud
Copy link

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 13 Code Smells

41.3% 41.3% Coverage
2.0% 2.0% Duplication

idea Catch issues before they fail your Quality Gate with our IDE extension sonarlint SonarLint

@openshift-ci
Copy link

openshift-ci bot commented Oct 17, 2023

@saswatamcode: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/sonarcloud a64109d link true /test sonarcloud

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@subbarao-meduri subbarao-meduri merged commit 1d6732a into stolostron:main Oct 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants