EnMasseProject / enmasse

EnMasse - Self-service messaging on Kubernetes and OpenShift
https://enmasseproject.github.io
Apache License 2.0
190 stars 87 forks source link

Design for address space bridging #2306

Open lulf opened 5 years ago

lulf commented 5 years ago

Overview

A commonly requested feature is the ability to bridge address spaces. I.e. have clients in address space A be able to send/receive from addreesses in Address space B.

Design

TODO

Tasklist

TODO

rgodfrey commented 5 years ago

Overview

This document describes alternate mechanisms for exposing addresses within one addresspace such that they can be reached from a second address space.

Design

An address space view consists of a restriction over the available addresses within an address space, associating permissions (send and/or receive) with each address within the view. The address space owner can then define which other address spaces (managed by the same enmasse installation) will have access to the view.

Option a)

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceView
metadata:
  name: myspace.myview
spec:
  addresses:
    - name: foo
      operations: [ send, receive ]
    - name: bar*
      operations: [ receive ]
  addressspaces: [ namespace1.A, namespace2.B ] 

Option b)

Separate view definition from view exposure

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceView
metadata:
  name: myspace.myview
spec:
  addresses:
    - name: foo
      operations: [ send, receive ]
    - name: bar*
      operations: [ receive ]

and ...

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceViewVisibility
metadata:
  name: myspace.myview
spec:
  addressspaces: [ namespace1.A, namespace2.B ]     

Option c)

Add the view definitions into the address space

apiVersion: enmasse.io/v1beta1
kind: AddressSpace
metadata:
  name: myspace
spec:
  type: standard
  plan: standard-unlimited
  views:
    - name: myview
      addresses:
        - name: foo
          operations: [ send, receive ]
        - name: bar*
          operations: [ receive ]
    - name: myview2
      addresses:
        - name: foo
          operations: [ receive ]          

while still separating the visibility

 apiVersion: admin.enmasse.io/v1beta1
 kind: AddressSpaceViewVisibility
 metadata:
   name: myspace.myview
 spec:
   addressspaces: [ namespace1.A, namespace2.B ]     
lulf commented 5 years ago

An alternative d) for consideration (not prefix view with address space, makes it possible to 'reuse' view):

apiVersion: enmasse.io/v1beta1
kind: AddressSpace
metadata:
  name: myspace
spec:
  type: standard
  plan: standard-unlimited
  views:
    - myview
    - thatview

And

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceView
metadata:
  name: myview
spec:
  addressSpaces: [ namespace1.A, namespace2.B ]
  addresses:
    - name: foo
      operations: [ send, receive ]
    - name: bar*
      operations: [ receive ]
k-wall commented 5 years ago

From an OO model point of view I find b) most appealing. I dislike the fact that information about addresses leaks back into the addressspace in c). I also find Rob's argument that deployment information should be separate persuasive (supporting the separation of AddressSpaceViewVisibility and AddressSpaceView).

rgodfrey commented 5 years ago

OK - so I suggest we go with a slightly modified option b) - renaming AddressSpaceViewVisibility to AddressSpaceViewAccess

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceView
metadata:
  name: myspace.myview
spec:
  addresses:
    - name: foo
      operations: [ send, receive ]
    - name: bar*
      operations: [ receive ]

and ...

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceViewAccess
metadata:
  name: myspace.myview
spec:
  addressspaces: [ namespace1.A, namespace2.B ]     

Limitations

sending to an address will be limited to addresses of type queue, topic, anycast and multicast (i.e. you can't send to a subscription). Receiving will be limited to types queue, anycast, multicast and subscription (i.e. you won't be able to receive from a topic in the first instance)

Bridging

To bridge addresses from a remote addressspace to the local address space, an AddressSpace Bridge needs to be created. In the first instance, only standard (i.e. not brokered) address spaces will support AddressSpaceBridge.

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceBridge
metadata:
  name: myspace.mybridge
spec:
  view: namespace.myview
  addressPrefix: foo      

The address bar made visible in the view namespace.myview with be reachable with the address foo/bar in the local addressspace myspace

lulf commented 5 years ago

I'm ok with the updated proposal, but I'm wondering if we should prefix the views etc. with the address space name or not. Would another approach be to reference these from the address space? Alternatively reference the address space in the spec? Putting a semantic meaning into metadata.name should be avoided if we can IMO.

rgodfrey commented 5 years ago

I'm ok with the updated proposal, but I'm wondering if we should prefix the views etc. with the address space name or not. Would another approach be to reference these from the address space? Alternatively reference the address space in the spec? Putting a semantic meaning into metadata.name should be avoided if we can IMO.

@lulf yeah - I wondered about that, I was thinking about putting the address space name in both AddressSpaceView and AddressSpaceBridge . For AddressSpaceViewAccess what do you think - have the AddressSpaceView name in the spec section? In AddressSpaceBridge the view reference will still need to be namespace.view or would need to be a map of { namespace: A, addressSpaceView: view } or something

lulf commented 5 years ago

How about:

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceView
metadata:
  name: myview
spec:
  addressSpace: {
    "name": "myspace",
    "namespace": "namespace"
  }
  addresses:
    - name: foo
      operations: [ send, receive ]
    - name: bar*
      operations: [ receive ]
apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceViewAccess
metadata:
  name: myviewaccess
spec:
  view: {
    "name": "myview",
    "namespace": "namspaceN"
  }
  addressspaces: [
    {
      "namespace": "namespace1",
      "name": "A"
    }
  ]
}
apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceBridge
metadata:
  name: mybridge
spec:
  addressSpace: {
    "name": "myspace",
    "namespace": "namespace1"
  }
  view: {
   "namespace": "namespaceN",
   "name": "myview"
  }
  addressPrefix: foo    

We can omit the namespace to imply the same namespace as the 'current' resource. We should also consider if we want to set some restrictions that makes the use of namespace relevant or not. I think maybe we shouldn't put that kind of restriction.

rgodfrey commented 5 years ago

@lulf Looks good to me, other than for AddressSpaceView and AddressSpaceViewAccess I think these must be defined in the same namespace as the AddressSpace so

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceView
metadata:
  name: myview
spec:
  addressSpace: "myspace"
  addresses:
    - name: foo
      operations: [ send, receive ]
    - name: bar*
      operations: [ receive ]
apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceViewAccess
metadata:
  name: myviewaccess
spec:
  view:  "myview"
  addressspaces: [
    {
      "namespace": "namespace1",
      "name": "A"
    }
  ]

is sufficient I think. And for the bridge, the bridge must be in the same namespace as the addressspace the bridge is being applied to so

apiVersion: admin.enmasse.io/v1beta1
kind: AddressSpaceBridge
metadata:
  name: mybridge
spec:
  addressSpace:  "myspace"
  view: {
   "namespace": "namespaceN",
   "name": "myview"
  }
  addressPrefix: foo
rgodfrey commented 5 years ago

So, in addition to the proposal above, I think we need to consider how we can bridge to individual addresses which may not be in an address space managed by the same enmasse instance. That is having some way to define a remote network endpoint and associated credentials, and a set of addresses reachable at that endpoint, and the available operations (read/write) on those addresses.

Finally I wonder if we should add some sort of mechanism to automatically forward messages from a "local" address/queue to a remote address/queue (or vice versa)