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

uniter: Relations between subordinates shouldn't keep the sub units alive #7603

Merged
merged 4 commits into from Jul 6, 2017

Conversation

babbageclunk
Copy link
Contributor

@babbageclunk babbageclunk commented Jul 6, 2017

Description of change

Relating two subordinates and then trying to remove the principal application would leave the units of the application in terminating state. The principal units wouldn't be cleaned up until their subordinates were, and they wouldn't die because the sub-sub relation would keep them alive. For example, if you had this configuration:

mysql/0
    ntp/0
    nrpe/0

...and nrpe and ntp were also related, then mysql/0 wouldn't get removed if you removed mysql.

Fix this by making the subordinate units only consider the relations to their principal when checking whether they should destroy themselves.

QA steps

  • Deploy the following bundle:
series: xenial
machines:
  '0':
    series: xenial
services:
  min:
    charm: cs:ubuntu-10
    num_units: 1
    to:
      - "0"
  nrpe:
    charm: cs:nrpe-23
  ntp:
    charm: cs:ntp-18
relations:
- - min:juju-info
  - nrpe:general-info
- - ntp:nrpe-external-master
  - nrpe:nrpe-external-master
- - ntp:juju-info
  - min:juju-info
  • Wait for the three units to become idle.
  • Remove the min application.
  • It should remove cleanly.

Bug reference

Fixes part of https://bugs.launchpad.net/juju/+bug/1702636

Copy link

@mjs mjs left a comment

Choose a reason for hiding this comment

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

Nice work

// OtherApplication returns the name of the application on the other
// end of the relation (from this unit's perspective).
func (r *Relation) OtherApplication() string {
return r.otherApp
Copy link

Choose a reason for hiding this comment

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

Just curious, what is otherApp for peer relations?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It'll be populated with the same app. It's obtained using relation.RelatedEndpoints(thisApp), which uses counterpartRole - for peer that returns peer. I think that's correct. It won't have any impact for this change though, since a peer relation couldn't ever be a principal one - the app would have to be both subordinate and insubordinate. :)


// RelationResults holds the result of an API call that returns
// information about multiple relations.
type RelationResults struct {
Copy link

Choose a reason for hiding this comment

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

Maybe move this above RelationResult so that all the RelationResult structs are next to each other?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wilco

// NewUniterAPIV4 creates an instance of the V4 uniter API.
func NewUniterAPIV4(st *state.State, resources facade.Resources, authorizer facade.Authorizer) (*UniterAPIV4, error) {
uniterAPI, err := NewUniterAPI(st, resources, authorizer)
uniterAPI, err := NewUniterAPIV5(st, resources, authorizer)
Copy link

Choose a reason for hiding this comment

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

This is weird (constructing V5 in V4) but I think I get it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's what was happening before anyway (there was an invisible V5 at the end of NewUniterAPI that became visible when V6 sprang into existence). The differences between the API versions are cumulative - if we just embedded UniterAPI in UniterAPIV4 we'd need to copy the V5 methods into it as well.

We could do it the other way around, implementing V5 in terms of V4 and V6 embedding V5, but it seems clearer to have the current version be the default case and the older (hopefully smaller) ones the deltas.

This required changing the return type of Relation and RelationById and
bumping the uniter API to version 6 (leaving a V5 that returns the old
types). The new field will be used in the uniter worker to determine
whether the relation can keep a subordinate unit alive.
@babbageclunk
Copy link
Contributor Author

$$merge$$

@jujubot
Copy link
Collaborator

jujubot commented Jul 6, 2017

Status: merge request accepted. Url: http://juju-ci.vapour.ws:8080/job/github-merge-juju

@jujubot
Copy link
Collaborator

jujubot commented Jul 6, 2017

Build failed: Tests failed
build url: http://juju-ci.vapour.ws:8080/job/github-merge-juju/11273

@babbageclunk
Copy link
Contributor Author

Grr, why are all of these tests making assertions about the version of the API?

This will be used by the uniter to determine whether the relation to the
principal unit is still alive.
Previously the uniter would only destroy the unit when all of its
container-scoped relations died - this meant that a relation to another
subordinate unit under the same principal could keep it alive.

Make ordering of relations deterministic for testing.
@babbageclunk
Copy link
Contributor Author

$$merge$$

@jujubot
Copy link
Collaborator

jujubot commented Jul 6, 2017

Status: merge request accepted. Url: http://juju-ci.vapour.ws:8080/job/github-merge-juju

@jujubot jujubot merged commit 093959c into juju:2.2 Jul 6, 2017
@babbageclunk babbageclunk deleted the uniter-subsub branch July 6, 2017 23:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants