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

Add PDB #204

Merged
merged 10 commits into from
Jul 26, 2024
Merged

Add PDB #204

merged 10 commits into from
Jul 26, 2024

Conversation

wejdross
Copy link
Member

Summary

  • to prevent downtime caused by software error after maintenance we need PDBs for our HA databases

Checklist

  • Categorize the PR by setting a good title and adding one of the labels:
    bug, enhancement, documentation, change, breaking, dependency
    as they show up in the changelog
  • Update tests.
  • Link this PR to related issues.

@wejdross wejdross self-assigned this Jul 24, 2024
@wejdross wejdross requested review from a team, Kidswiss, TheBigLee and zugao and removed request for a team July 24, 2024 16:26
@wejdross wejdross added the enhancement New feature or request label Jul 24, 2024
keycload.yaml Outdated Show resolved Hide resolved
pkg/comp-functions/functions/common/interfaces.go Outdated Show resolved Hide resolved
pkg/comp-functions/functions/common/pbp.go Outdated Show resolved Hide resolved
}
pdb, ok := obj.(PDB)
if !ok {
return runtime.NewWarningResult(fmt.Sprintf("Type %s doesn't implement PDB interface", reflect.TypeOf(obj).String()))
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd also return a fatal here, as that's an error that could only happen if the XRD is wrongly implemented.

pkg/comp-functions/functions/common/pbp.go Outdated Show resolved Hide resolved
emptyMap := map[string]string{}

// to add new case, simply print labels, for example `kubectl -n vshn-mariadb-something-123sa get pod mariadb-something-123sa-0 -o json | jq .metadata.labels` and add the label to the map
switch obj.(type) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This won't scale, ideally the comp should know the necessary labels and return them as part of the PDB interface.

case *v1.VSHNKeycloak:
emptyMap["app.kubernetes.io/name"] = obj.GetLabels()["crossplane.io/composite"]
case *v1.VSHNPostgreSQL:
emptyMap["stackgres.io/cluster-name"] = obj.GetLabels()["crossplane.io/composite"] + "-pg"
Copy link
Contributor

@Kidswiss Kidswiss Jul 25, 2024

Choose a reason for hiding this comment

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

For nested services using obj.GetLabels()["crossplane.io/composite"] will be very problematic as it will always point to the composite belonging to the claim, which might be another service like nextcloud and thus have another name. For example, the -pg appendix you have here only applies to PG instances that are nested with Nextcloud or Keycloak. A normal PostgreSQL instance doesn't have that appendix.

Just use obj.GetName() that will return the right value because obj is our composite anyway.

@wejdross wejdross requested a review from Kidswiss July 25, 2024 15:56
return runtime.NewFatalResult(fmt.Errorf("can't get composite: %w", err))
}
pdb, ok := comp.(PDB)
if !ok {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be great to catch this problem at build time and not at runtime. I thought about a solution here but nothing comes into my mind. @Kidswiss maybe you have an idea here?

Copy link
Contributor

Choose a reason for hiding this comment

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

I tried to think of something during my first review, unfortunately I wasn't able to get a working idea.

I'll have another look now that all my other remarks have been implemented.

Copy link
Contributor

Choose a reason for hiding this comment

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

Huh... okay it's actually rather simple:

Make the PDB interface also implement client.Object:

type PDB interface {
	GetInstanceNamespace() string
	GetInstances() int
	GetPDBLabels() map[string]string
	client.Object
}

Accept PDB in the AddPDBSettings function:

func AddPDBSettings(comp PDB) func(ctx context.Context, svc *runtime.ServiceRuntime) *fnproto.Result {

Remove the type assert and rename all pdb variables to comp. No more type assertion needed and the compiler will scream at you if you forget to implement the interface.

Copy link
Collaborator

@zugao zugao Jul 26, 2024

Choose a reason for hiding this comment

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

perfect. Awesome. Thanks for this :)

Copy link
Member Author

Choose a reason for hiding this comment

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

the whole point I wanted to keep it in different interface was that not all services are ready for HA from the beginning, not all services even have a field instances in their claim. Now it's using InfoGetter{} as mentioned in the beginning and I completely got rid of PDB{} interface

Copy link
Contributor

Choose a reason for hiding this comment

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

The idea of my comment wasn't to get rid of the PDB interface completely, just reduce the amount of duplication.

not all services even have a field instances in their claim.

In the long run we want all our service to have HA as well.

Copy link
Contributor

Choose a reason for hiding this comment

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

@wejdross you can use the interface Composite here, it will satisfy all necessary functions. Then you can get rid of the type assertion.

@wejdross
Copy link
Member Author

@zugao @Kidswiss I just pushed new commit doing a small cleanup with interfaces and enabling it for Minio. By the way, compiler catches if type implement the interface, I could probably delete that check, I rather want to be double sure here

@wejdross wejdross requested a review from zugao July 26, 2024 07:53
@@ -324,3 +324,9 @@ func (v *VSHNKeycloak) GetMonitoring() VSHNMonitoring {
func (v *VSHNKeycloak) GetInstances() int {
return v.Spec.Parameters.Instances
}

func (v *VSHNKeycloak) GetPDBLabels() map[string]string {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please add this to hack/bootstrap/template/api.txt?

@Kidswiss
Copy link
Contributor

@zugao @Kidswiss I just pushed new commit doing a small cleanup with interfaces and enabling it for Minio. By the way, compiler catches if type implement the interface, I could probably delete that check, I rather want to be double sure here

I've added a comment how to make it work: #204 (comment)

@zugao
Copy link
Collaborator

zugao commented Jul 26, 2024

By the way, compiler catches if type implement the interface

Since you get already the PDB object in the function there's no need to check for anything else at runtime. It should work and in worse case scenario (which should not happen) the application will panick

Copy link
Collaborator

@zugao zugao left a comment

Choose a reason for hiding this comment

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

Now looks great and clean

}
log.Info("HA detected, adding pdb", "service", comp.GetName())

min := intstr.IntOrString{IntVal: int32(comp.GetInstances()) / 2}
Copy link
Collaborator

@zugao zugao Jul 26, 2024

Choose a reason for hiding this comment

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

  1. I'm not sure this will work for uneven numbers.
  2. I get this warning in my IDE for variable min:
 Inspection info: Reports declarations of variables, arguments or functions that overlap with the built-in or reserved keyword.
If you receive this error then your code might not be as explicit as possible and might confuse other users.
Example:
type byte struct{}
type string interface{}
Types byte and string collide with the built-in type aliases. Therefore, they will be highlighted. Consider renaming such declarations

Maybe the reason why 50% does not work because of the 2 point?

}
log.Info("HA detected, adding pdb", "service", comp.GetName())

min := intstr.IntOrString{IntVal: int32(comp.GetInstances()) / 2}
Copy link
Contributor

Choose a reason for hiding this comment

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

If the string doesn't work, can we at least make sure that we always round up here? Then we'll have the same functionality as using 50%

Copy link
Member Author

Choose a reason for hiding this comment

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

ok, I found the issue with 50%, Type: intval is default one, when setting a strVal: "50%", You must add explicitly Type: strVal

@zugao zugao self-requested a review July 26, 2024 13:11
Copy link
Collaborator

@zugao zugao left a comment

Choose a reason for hiding this comment

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

Needs a bit more rework

Copy link
Collaborator

@zugao zugao left a comment

Choose a reason for hiding this comment

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

From my side now it's ok. Please resolve all Simon's concerns and make sure you don't go back to casting approach.

@wejdross wejdross merged commit e31ca9b into master Jul 26, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants