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

K8SPS-266: Refactor Replicator interface #517

Merged
merged 15 commits into from
Jan 17, 2024
Merged

Conversation

inelpandzic
Copy link
Contributor

@inelpandzic inelpandzic commented Jan 8, 2024

K8SPS-266 Powered by Pull Request Badge

CHANGE DESCRIPTION

Problem:
The Replicator interface was very bloated and could be refactored to be much simpler.

Solution:
Remove the Replicator interface altogether by essentially splitting it into two parts - the one used in our binaries cmd/healthcheck and cmd/bootstrap (connects to mysql via the driver - directly) and other that is used by the operator (connects to mysql via exec).

Now we have:

  • cmd/db DB type which is used by healthcheck and bootstrap
  • pkg/db db type which is used by the operator

pkg/db db is encapsulated in pkg/db ReplicationDBManager used in ps/controller and psbackup/controller, and in pgk/db UserDBManager used in ps/user.

Besides this two more things are refactored:

  • Getting replication topology
  • Removed everything with exec in the name that was left when making the operator run localy

This PR fixes this task as well: https://perconadev.atlassian.net/browse/K8SPS-256

CHECKLIST

Jira

  • Is the Jira ticket created and referenced properly?
  • Does the Jira ticket have the proper statuses for documentation (Needs Doc) and QA (Needs QA)?
  • Does the Jira ticket link to the proper milestone (Fix Version field)?

Tests

  • Is an E2E test/test case added for the new feature/change?
  • Are unit tests added where appropriate?

Config/Logging/Testability

  • Are all needed new/changed options added to default YAML files?
  • Are the manifests (crd/bundle) regenerated if needed?
  • Did we add proper logging messages for operator actions?
  • Did we ensure compatibility with the previous version or cluster upgrade process?
  • Does the change support oldest and newest supported PS version?
  • Does the change support oldest and newest supported Kubernetes version?

@@ -0,0 +1,240 @@
package db
Copy link
Contributor

Choose a reason for hiding this comment

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

I’m not sure about this cmd/db. For me cmd should be consumers of the API not providers and I find depending on a cmd package from another cmd package a bit counterintuitive.

what do you think of something like this?

pkg/mysql
├── client
│   ├── direct_client.go
│   └── exec_client.go
├── config.go
├── mysql.go
└── topology
    └── topology.go

and consumers can create instances like:

client.NewExecClient(...)
client.NewDirectClient(...)

Copy link
Contributor Author

@inelpandzic inelpandzic Jan 16, 2024

Choose a reason for hiding this comment

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

cmd/mysql/client.go `ReplicationManager`
- StartReplication(ctx context.Context, host, replicaPass string, port int32) error
- StopReplication(ctx context.Context) error
- ResetReplication(ctx context.Context) error
- ReplicationStatus(ctx context.Context) (db.ReplicationStatus, string, error)                  
- IsReplica(ctx context.Context) (bool, error)
- DisableSuperReadonly(ctx context.Context) error
- IsReadonly(ctx context.Context) (bool, error)
- ReportHost(ctx context.Context) (string, error)
- CloneInProgress(ctx context.Context) (bool, error)
- Clone(ctx context.Context, donor, user, pass string, port int32) error
- DumbQuery(ctx context.Context)
- GetMemberState(ctx context.Context, host string) (db.MemberState, error)                       
- CheckIfInPrimaryPartition(ctx context.Context) (bool, error)
- EnableSuperReadonly(ctx context.Context) error
- Close() error


pkg/mysql/client/replication.go `ReplicationManager`
- ChangeReplicationSource(ctx context.Context, host, replicaPass string, port int32) error
- ReplicationStatus(ctx context.Context) (ReplicationStatus, string, error)                      
- GetGroupReplicationPrimary(ctx context.Context) (string, error)
- GetGroupReplicationReplicas(ctx context.Context) ([]string, error)
- GetMemberState(ctx context.Context, host string) (MemberState, error)                          


pkg/mysql/client/users.go `UserManager`
- DiscardOldPasswords(ctx context.Context, users []mysql.User) error
- UpdateUserPasswords(ctx context.Context, users []mysql.User) error

As you can see the structure of these three components, there are three different and distinct things, meaning, there is nothing in common between them so we could have a single interface with different implementations. If we want some interfaces they would be like three different ones with implementation for each of them and that is not necessary. If we want something that you suggested, we would more-or-less have something similar that we had before, and I wouldn't like that.

Thats why I still suggest a structure like this, with only types that expose certain methods for these three use cases. The thing that I think is good from the suggestion is the location of everything. I like more to have pkg/mysql/client/... rather than pkg/db, much better.

And regarding your concern Ege about like a cmd importing cmd/db, that is OK and it should not necesseraliy come from pkg/..., because it is related only to cmd. Imagine having some common util that is needed for different stuff in cmd, you wouldn't put it in pkg. And because I also wanted to confirm this opinion of mine, I looked at Docker and Kubernetes source code and this is a common thing there as well.

With all of this, everything in here is nicely separated and clear, and most importantly, simple without unnecessary complications.

Replicas []string
}

func (r *PerconaServerMySQLBackupReconciler) getTopology(ctx context.Context, cluster *apiv1alpha1.PerconaServerMySQL, operatorPass string) (Topology, error) {
Copy link
Contributor

@pooknull pooknull Jan 10, 2024

Choose a reason for hiding this comment

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

I don't like the idea of removing the pkg/mysql/topology package and adding a new method to the reconciler. This could potentially make the reconciler excessively complex and difficult to refactor when making changes related to topology, such as the ones proposed in this PR.

I think the reconciler should have methods that are only responsible for managing the cluster, without retrieving any data from the database. The pkg/db package is more suitable for that purpose.

If the topology is only used for the pkg/controller/psbackup package, then let's move pkg/mysql/topology to the pkg/controller/psbackup/topology

Copy link
Contributor Author

@inelpandzic inelpandzic Jan 15, 2024

Choose a reason for hiding this comment

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

I see your point, but why I don't necessarily agree is that of having a whole package for only one thing used in one place. And the reconciler is calling the database all over the place, the way it manages the cluster involves calling DB, so I don't see the problem with this in that sense. I can agree that having a method on the reconciler like this is not nice, but having a simple function is OK in my opinion.

I figured out that you introduced this topology package because of the proposed PR, but what I suggest is that we don't design our code for the future that might never happen, it can just complicate things uneccesarily. When we need it we can introduce whatever we want.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree that it's too much to create a separate package. But I don't want to add another method to reconciler, even if it's simple. We can try to make it a function instead of a method. We can also just put this function in a separate file, such as pkg/mysql/psbackup/topology.go. What do you think?

Actually, I don't think my suggestion is worth wasting time on. This is not a critical problem, so I'll approve the PR as soon as @egegunes' suggestions are resolved.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree with you Andrii, getting the topology from the reconciler is not that nice, like I said, better maybe to have it in a function. But even if we have it it will not stick out, we have something similar with isGRReady on PerconaServerMySQLReconciler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@egegunes egegunes mentioned this pull request Jan 15, 2024
11 tasks
@egegunes egegunes added this to the v0.7.0 milestone Jan 16, 2024
egegunes
egegunes previously approved these changes Jan 16, 2024
pooknull
pooknull previously approved these changes Jan 16, 2024
@inelpandzic inelpandzic dismissed stale reviews from pooknull and egegunes via 8831094 January 16, 2024 09:10
@JNKPercona
Copy link
Collaborator

Test name Status
async-ignore-annotations passed
auto-config passed
config passed
config-router passed
demand-backup passed
gr-demand-backup passed
gr-demand-backup-haproxy passed
gr-haproxy passed
gr-ignore-annotations passed
gr-init-deploy passed
gr-one-pod passed
gr-recreate passed
gr-scaling passed
gr-self-healing passed
gr-tls-cert-manager passed
gr-users passed
haproxy passed
init-deploy passed
limits passed
monitoring passed
one-pod passed
operator-self-healing passed
recreate passed
scaling passed
service-per-pod passed
sidecars passed
smart-update passed
tls-cert-manager passed
users passed
version-service passed
We run 30 out of 30

commit: b184ccf
image: perconalab/percona-server-mysql-operator:PR-517-b184ccf

@hors hors merged commit 0e5401a into main Jan 17, 2024
13 checks passed
@hors hors deleted the K8SPS-266-refactor-replicator branch January 17, 2024 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/XXL 1000+ lines
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants