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

[spec][backwards incompatible] drop support for v1beta1 #331

Merged
merged 1 commit into from
Aug 15, 2018

Conversation

surajssd
Copy link
Contributor

@surajssd surajssd commented Aug 8, 2018

This commit removes the support for v1beta1 resource type. The
only supported version is only v1beta2.

@surajssd surajssd changed the title [spec][backwards incompatible] drop support for v1beta1 [WIP][spec][backwards incompatible] drop support for v1beta1 Aug 8, 2018
@surajssd surajssd force-pushed the surajssd/remove-v1beta1 branch 2 times, most recently from fc5bd73 to f83742a Compare August 9, 2018 06:07
@surajssd surajssd changed the title [WIP][spec][backwards incompatible] drop support for v1beta1 [spec][backwards incompatible] drop support for v1beta1 Aug 9, 2018
@krnowak
Copy link
Contributor

krnowak commented Aug 9, 2018

There seem to be a misunderstanding what this task was about. And the fact that we have this customVersion hack does not really help here.

So, so far our CRD has version habitat.sh/v1beta1. At some point we wanted to make an incompatible change (we switched from using Deployments to StatefulSets), so we wanted to introduce version habitat.sh/v1beta2. That didn't work - k8s at the time didn't have support for multiple versions of the CRD. It means that registering multiple versions failed and we needed to have it, because we still wanted to support the old version (with Deployments).

That's why we came up with the customVersion thing. It is a toplevel field which is our hacky take on CRD versioning. So if the field is absent in the manifest or if it is equal to v1beta1 then we expect yamls like:

apiVersion: habitat.sh/v1beta1

customVersion: v1beta1 # or unspecified
spec:
  image: habitat/redis-hab
  count: 1
  

But if the customVersion field is equal to v1beta2 then we expect something like:

apiVersion: habitat.sh/v1beta2

customVersion: v1beta2
spec:
  v1beta2:
    image: habitat/redis-hab
    count: 1
    

I suppose if we wanted to make another incompatible change in the manifest, we would add v1beta3 as a possible value for customVersion and v1beta3 field under spec, just like for v1beta2.

At some point we declared v1beta1 customVersion as deprecated and now we want to remove it. This currently means that customVersion field must be specified and must be equal to v1beta2 (until we introduce something like v1beta3 then this value would also be valid). So unspecified customVersion field or customVersion = v1beta1 are not supported anymore. This also means that the official CRD version is still v1beta1.

This customVersion hack is a thing we will need to keep until all versions of k8s the operator supports support CRD versioning. Basic form of CRD versioning arrived to k8s 1.11, not sure if it is in any way usable for us - I haven't yet investigated that. So you can see that this hack will stay with us a little while longer.

So about your changes: there is no need to change the CRD version. Keeping the CRD version intact should drop the need for renaming the directories, fixing the examples (the v1beta1 example still needs to be dropped though), resource names in tests, import paths in source files and some paths in bash scripts.

Oh, and thanks for the tests, they are always useful!

@surajssd surajssd force-pushed the surajssd/remove-v1beta1 branch 3 times, most recently from 051f9c9 to f4dd7ee Compare August 10, 2018 10:23
@surajssd
Copy link
Contributor Author

@krnowak made changes as you requested PTAL!

if err := v1beta2(ctx, &wg, cSets, logger); err != nil {
level.Error(logger).Log("msg", err)
cancelFunc()
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure what's the point of this cancel function invocation as returning immediately after that will all os.Exit(…) which in turn just kills all the running goroutines. So what we can do here is one of the following:

  • just drop cancelFunc() here
    • otherwise it feels to be pointless, as other goroutines will likely have no time to respond to the cancellation
  • keep it
    • it probably won't do any harm anyway
  • keep it and add a wait on wg.Wait()
    • that probably would be ideal from the "cleanup" point of view, but it may hang if:
      • the operator failed to register the CRD for some other reason than the CRD already being registered, or if
      • the operator failed to create a controller
    • we probably could add wg.Done() in the v1beta2 function in the error paths, but that would basically be the same as keeping only the cancelFunc invocation from goroutines point of view, so no good
    • after writing all of the above I had a closer look at the v1beta2 function and I think that calling cancelFunc() is pointless for another reason - both error paths in v1beta happen before ctx is passed anywhere, so if an error happens then nothing listens on the ctx.Done(), so calling cancelFunc() here has no effects.

So I'd say, just drop it, please.

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 that program fails so all the resources will be reclaimed, but go vet keeps complaining since it does not find cancelFunc being called in all of it's exit paths.

Added defer cancelFunc(), we can call cancelFunc() multiple times without a problem. Here IMO we could follow good practices of golang so even if the code is moved or refactored the reclaimation still exists.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmph, go vet go shmet. Alright, let's keep it like that.

@@ -5,7 +5,6 @@ metadata:
labels:
source: operator-example
app: standalone-habitat
customVersion: v1beta2
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to stay as is - with dropping the customVersion for v1beta1, this field became mandatory. Lack of this field had the same meaning as it being specified to v1beta1. Now that we are dropping v1beta1 custom version, the customVersion field basically stops being optional.

We don't want to make an unspecified customVersion field the same as specifying it as v1beta2, because all the valid (but deprecated) v1beta1 manifests will suddenly be interpreted as v1beta2 which is just wrong.

Copy link
Contributor Author

@surajssd surajssd Aug 13, 2018

Choose a reason for hiding this comment

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

done

@@ -45,21 +45,12 @@ type Habitat struct {
// multiple versions of a CRD. It encodes the actual version of the type, so
// that controllers can decide whether to discard an object if the version
// doesn't match.
// When absent, it defaults to v1beta1.
// When absent, it defaults to v1beta2.
Copy link
Contributor

Choose a reason for hiding this comment

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

Please drop this line and the one below (+optional). The field became mandatory. It needs to stay as a pointer though, unfortunately, but that's hacks for us.

Copy link
Contributor Author

@surajssd surajssd Aug 13, 2018

Choose a reason for hiding this comment

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

done

if err := checkCustomVersionMatch(hab); err != nil {
level.Debug(hc.logger).Log("msg", err)
if err := checkCustomVersionMatch(hab.CustomVersion); err != nil {
level.Error(hc.logger).Log("msg", err)
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 if this should be an error, but it certainly should be something more that debug. Info maybe? The reason it shouldn't be an error is that if we add another customVersion (say v1beta3) then we don't want v1beta2 controller spewing errors every time we send a valid v1beta3 manifest to the cluster.

I guess it would be nice to have a single way of catching wrong customVersion fields that would print the errors, but that is outside of the scope of this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, could you reword a bit a message of the commit that has those changes? It is not really only adding the tests to changed functions. It makes some functions easier to test too, so you added those tests as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When we add support for v1beta3 won't the code of checkCustomVersionMatch change?

Also this is user facing error which should be shown to user, but this rather gets dumped in the operator logs. I have summarized some of my thoughts here #335

Copy link
Contributor Author

@surajssd surajssd Aug 13, 2018

Choose a reason for hiding this comment

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

Also, could you reword a bit a message of the commit that ...

Yes would take care of it.

Copy link
Contributor

Choose a reason for hiding this comment

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

we add support for v1beta3 won't the code of checkCustomVersionMatch change?

Unlikely, but who knows? So far, when we added a new custom version we basically duplicated the controller and then made some changes relevant for the new custom version. We did so because we wanted to avoid unintended changes in the older controller when changing something in the newer one.

As of user facing errors - maybe resolving this issue would help: #185

"k8s.io/apimachinery/pkg/types"
)

func Test_habitatKeyFromLabeledResource(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just TestHabitatKeyFromLabeledResource.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

}{
{
name: "nothing specified in the version",
wantErr: false,
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be true. And consider specifying arg as nil explicitly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done


import "testing"

func Test_checkCustomVersionMatch(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

TestCheckCustomVersionMatch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -283,8 +283,8 @@ func TestPersistentStorage(t *testing.T) {
}
}

func TestV1beta1(t *testing.T) {
h, err := utils.ConvertHabitat("resources/v1beta1/habitat.yml")
func TestV1beta2(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can drop this test altogether. The v1beta2 is rather tested extensively in other test cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -0,0 +1,17 @@
apiVersion: habitat.sh/v1beta2
Copy link
Contributor

Choose a reason for hiding this comment

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

If we decide to drop TestV1beta1 test instead of renaming it to TestV1beta1 then this file will be unnecessary and can be dropped too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -79,9 +79,7 @@ const (
// Event messages.
messageValidationFailed = "Failed validating Habitat"
messageCMCreated = "Created peer IP ConfigMap"
messageCMUpdated = "Updated peer IP ConfigMap"
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you figure out why these are unused? Maybe we should use them somewhere instead of dropping those? Maybe there will be some notes in some PR that introduced those fields. CC @kosyfrances

Also, this change could be done in a separate commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

This commit removes the support for `v1beta1` resource type. The
only supported version is only `v1beta2` inside spec.

Also updates the function definition of `checkCustomVersionMatch` to
accept string pointer, which is used to verify the supported version
of the CR definition spec.

Signed-off-by: Suraj Deshmukh <suraj@kinvolk.io>
@surajssd
Copy link
Contributor Author

@krnowak all changes done!

@krnowak
Copy link
Contributor

krnowak commented Aug 15, 2018

LFAD, thanks!

@krnowak krnowak merged commit 495365e into habitat-sh:master Aug 15, 2018
@krnowak krnowak deleted the surajssd/remove-v1beta1 branch August 15, 2018 07:11
Copy link
Contributor

@indradhanush indradhanush left a comment

Choose a reason for hiding this comment

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

A late review. More like open questions than a review really.

offer support for persistence.

Because this is a backwards-incompatible change, it was decided to implement it
under a different custom version.
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it have made sense to keep the message about customVersion and why it was implemented in the first place for historical reasons? Ofcourse the difference between v1beta1 and v1beta2 is irrelevant now. :)

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 don't know if we should add that back again, but if you recommend so, I can do that? Not sure if current design doc should be a place to keep it though. I can add a line which talks about only customVersion is hack since the versions <=1.10 don't support versioning of CRDs, and to get around it customVersion was added?

time, we defined the `customVersion` field, and let controllers decide which
objects to act upon based on its value (e.g. the `v1beta2` controller will
ignore `Habitat` objects whose `customVersion` field is not `v1beta2`.

Copy link
Contributor

Choose a reason for hiding this comment

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

More like this would have been the part worth preserving probably.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed since, it is not relevant to user in current state. But if we had mechanism like kubernetes docs website has where you can select the version of kubernetes and then docs reflect that version, that would have been great.

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.

3 participants