Add code to remoterelations worker to publish local changes to remoe model #6637

Merged
merged 1 commit into from Dec 2, 2016

Conversation

Projects
None yet
4 participants
Owner

wallyworld commented Nov 30, 2016

The remote relations worker gather the changes in response to a relation units watcher event, and calls the publish api on the remote relations facade to get said changes sent to the remote model.

To make things efficient, the ExportLocalEntity behaviour has been tweaked so that if an entity is exported twice, the existing token is returned with an AlreadyExists error to save a second api call.

QA: bootstrap lxd to ensure no breakages

Contributor

reedobrien commented Nov 30, 2016

!!build!!

LGTM, mostly curious questions.

apiserver/params/crossmodel.go
+ Name string `json:"name"`
+ Life Life `json:"life"`
+ Status string `json:"status"`
+ ModelUUID string `json:"model-uuid"`
@reedobrien

reedobrien Dec 1, 2016

Contributor

Other structs here have comments on the members. These seem self-evident (well they all do really), so maybe add for consistency. Or is there a rule of thumb I am missing.

@wallyworld

wallyworld Dec 1, 2016

Owner

Yeah, in this file the structs tended to have attribute comments, which makes it a PITA to add new structs. Elsewhere we don't bother. I'll add comments for consistency.

apiserver/params/crossmodel.go
@@ -340,7 +341,17 @@ type RemoteRelationsChange struct {
// RemoteRelationsChanges holds a set of RemoteRelationsChange structures.
type RemoteRelationsChanges struct {
- Changes []RemoteRelationsChange `json:"changes,omitempty"`
+ Changes []RemoteModelRelationsChange `json:"changes,omitempty"`
@reedobrien

reedobrien Dec 1, 2016

Contributor

Comment? (see earlier review comment)

apiserver/params/crossmodel.go
+ Changes []RemoteModelRelationsChange `json:"changes,omitempty"`
+}
+
+// RemoteModelRelationsChange holds the model uuid and changes to
@reedobrien

reedobrien Dec 1, 2016

Contributor

holds the remote model UUID? Or maybe more generic since the member variable is described.

@@ -44,7 +46,12 @@ func (st *mockState) ExportLocalEntity(entity names.Tag) (string, error) {
if err := st.NextErr(); err != nil {
return "", err
}
- return "token-" + entity.Id(), nil
+ if token, ok := st.exportedEntities[entity.Id()]; ok {
+ return token, errors.AlreadyExistsf(entity.Id())
@reedobrien

reedobrien Dec 1, 2016

Contributor

format string? Or NewAlreadyExists? Mock code so doesn't matter. Curious about choice here though.

@wallyworld

wallyworld Dec 1, 2016

Owner

NewAlreadyExists wraps an underlying error. We don't need that here. We just want an error satisfying IsAlreadyExists

@@ -24,7 +26,7 @@ type RemoteRelationsFacade interface {
@reedobrien

reedobrien Dec 1, 2016

Contributor

Comment mismatch RemoteRelationsFacade exposes ...

@@ -170,7 +177,9 @@ func (w *Worker) handleApplicationChanges(applicationIds []string) error {
logger.Debugf("started watcher for remote application %q", name)
appWorker, err := newRemoteApplicationWorker(
relationsWatcher,
+ result.Result.ModelUUID,
@reedobrien

reedobrien Dec 1, 2016

Contributor

Is there a size at which we switch to keyed fields?

@wallyworld

wallyworld Dec 1, 2016

Owner

Nothing explicit. I find keyed fields useful mainly for when there are nil defaults. Otherwise it's just unnecessary boilerplate.

+
+ remoteRelationId params.RemoteEntityId
+ remoteUnitIds map[string]params.RemoteEntityId
+
@reedobrien

reedobrien Dec 1, 2016

Contributor

s/Id/ID ?

@wallyworld

wallyworld Dec 1, 2016

Owner

RemoteEntityId is what's been used already elsewhere.

+ relationTag: relationTag,
+ ruw: ruw,
+ changes: changes,
+ remoteUnitIds: make(map[string]params.RemoteEntityId),
@reedobrien

reedobrien Dec 1, 2016

Contributor

s/Id/ID ? There's a bunch of these, so maybe it's just inertia/legacy.

Contributor

reedobrien commented Dec 1, 2016

QA checks out.

Status string `json:"status"`
+
+ // ModelUUID is the UUId of the model hosting the application.
@axw

axw Dec 1, 2016

Member

UUID. This shouldn't be needed though? We spoke about having the worker always talk to the controller, and the controller does the cross-model comms. The controller knows which model the remote application belongs to already.

@wallyworld

wallyworld Dec 1, 2016

Owner

I looked at how the JAAS code works and you make an API connection to the model facade on which you want to operate - the api code redirects as needed to the right controller. You still need the model uuid to do that. You get an the api connection info, set the model uuid, and open the api connection - the login process will redirect if the target controller is not the one hosting the model. From there, the worker just makes an api call to the facade which under the covers is connected to the correct target model.

axw approved these changes Dec 2, 2016

@@ -93,7 +94,10 @@ func (r *RemoteEntities) ExportLocalEntity(entity names.Tag) (string, error) {
return aa, nil
}
if err := r.st.run(ops); err != nil {
- return "", errors.Trace(err)
+ // Where error is AlreadyExists, we still return the
@axw

axw Dec 2, 2016

Member

can you please put this comment in the method doc also?

+ // and relation unit watcher can occur at any time.
+ // This prevents the possibility of the same unit being exported
+ // simultaneously.
+ exportMutex sync.Mutex
+ if err != nil {
+ return errors.Annotatef(err, "exporting relation %v", w.relationTag)
+ }
+ if results[0].Error != nil && results[0].Error.Code != params.CodeAlreadyExists {
@axw

axw Dec 2, 2016

Member

use params.IsCodeAlreadyExists?

+ changedUnitNames = append(changedUnitNames, name)
+ }
+ unitNamesToExport := append(changedUnitNames, change.Departed...)
+ logger.Debugf("exporting units: %v", unitNamesToExport)
@axw

axw Dec 2, 2016

Member

I suggest moving this to where we actually call the export API, otherwise this could get quite noisy

+ event := &params.RemoteRelationChangeEvent{
+ RelationId: w.remoteRelationId,
+ }
+ for i := range change.Departed {
@axw

axw Dec 2, 2016

Member

event.DepartedUnits = remoteId[len(changedUnitNames):]
?

Owner

wallyworld commented Dec 2, 2016

$$merge$$

Contributor

jujubot commented Dec 2, 2016

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

Contributor

jujubot commented Dec 2, 2016

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

Owner

wallyworld commented Dec 2, 2016

$$merge$$

Contributor

jujubot commented Dec 2, 2016

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

Contributor

jujubot commented Dec 2, 2016

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

Owner

wallyworld commented Dec 2, 2016

$$merge$$

Contributor

jujubot commented Dec 2, 2016

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

Contributor

jujubot commented Dec 2, 2016

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

Member

axw commented Dec 2, 2016

$$merge$$

Contributor

jujubot commented Dec 2, 2016

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

@jujubot jujubot merged commit 18705b3 into juju:develop Dec 2, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment