diff --git a/meta/io.murano.applications/Classes/replication.yaml b/meta/io.murano.applications/Classes/replication.yaml index ca2cc7f2..3b5c358b 100644 --- a/meta/io.murano.applications/Classes/replication.yaml +++ b/meta/io.murano.applications/Classes/replication.yaml @@ -45,17 +45,16 @@ Methods: deploy: Body: # release excessive replicas - - $newItems: $this.items.take($this.numItems) + - $oldItems: $this.items.take($this.numItems) - $itemsToRelease: $this.items.skip($this.numItems) - $this.provider.releaseReplicas($itemsToRelease) - - $this.items: $newItems - $delta: $this.numItems - len($this.items) - $startIndex: len($this.items) + 1 - $endIndex: $startIndex + $delta - $createdItems: range($startIndex, $endIndex).select( - $this.provider.createReplica($, $this)) - - $this.items: $this.items + $createdItems + $this.provider.createReplica($, $this)).takeWhile($ != null) + - $this.items: $oldItems + $createdItems scale: Arguments: @@ -69,11 +68,10 @@ Methods: - $this.numItems: min($this.numItems, $this.maxItems) - $this.deploy() - releaseItems: - Arguments: - items: - Contract: - - $.class(std:Object) + .destroy: + Body: + - $this.numItems: 0 + - $this.deploy() --- # ------------------------------------------------------------------ # --- @@ -92,6 +90,8 @@ Methods: replicas: Contract: - $.class(std:Object) + Body: + Return: $replicas --- # ------------------------------------------------------------------ # --- @@ -114,3 +114,105 @@ Methods: Body: - Return: new($this.template, $owner) + +--- # ------------------------------------------------------------------ # --- +# Replica provider that is a composition of other replica providers + +Name: CompositeReplicaProvider +Extends: ReplicaProvider + +Properties: + providers: + Contract: + - $.class(ReplicaProvider).notNull() + +Methods: + createReplica: + Arguments: + - index: + Contract: $.int().notNull() + - owner: + Contract: $.class(std:Object) + Body: + - Return: $this.providers.select($.createReplica($index, $owner)).where($ != null).first(null) + + releaseReplicas: + Arguments: + replicas: + Contract: + - $.class(std:Object) + Body: + - For: provider + In: $this.providers + Do: + - $replicas: $provider.releaseReplicas($replicas) + - If: $replicas = null or not $replicas.any() + Then: + Break: + - Return: $replicas + +--- # ------------------------------------------------------------------ # --- +# A replica provider from the prepopulated pool + +Name: PoolReplicaProvider +Extends: ReplicaProvider + +Properties: + pool: + Contract: + - $.class(std:Object).notNull() + + consumedItems: + Usage: Out + Contract: + - $.class(std:Object).notNull() + +Methods: + createReplica: + Arguments: + - index: + Contract: $.int().notNull() + - owner: + Contract: $.class(std:Object) + Body: + - $item: $this.pool.where(not $this.consumedItems.contains($)).first(null) + - If: $item != null + Then: + - $this.consumedItems: $this.consumedItems.append($item) + - Return: $item + + releaseReplicas: + Arguments: + replicas: + Contract: + - $.class(std:Object) + Body: + - $poolReplicas: $replicas.where($this.consumedItems.contains($)) + - $this.consumedItems: $this.consumedItems.where(not $poolReplicas.contains($)) + - Return: $replicas.where(not $poolReplicas.contains($)) + +--- # ------------------------------------------------------------------ # --- +# Replica provider with a load balancing that returns instance from the +# prepopulated list. Once the provider runs out of free items it goes to +# beginning of the list and returns the same instances again. + +Name: RoundrobinReplicaProvider +Extends: ReplicaProvider + +Properties: + items: + Contract: + - $.class(std:Object).notNull() + - 1 + +Methods: + createReplica: + Arguments: + - index: + Contract: $.int().notNull() + - owner: + Contract: $.class(std:Object) + Body: + - $index: $.getAttr(lastIndex, 0) + - $.setAttr(lastIndex, ($index + 1) mod len($this.items)) + - Return: $this.items[$index] diff --git a/meta/io.murano.applications/Classes/servers.yaml b/meta/io.murano.applications/Classes/servers.yaml index 0092a6f2..0e53a1c0 100644 --- a/meta/io.murano.applications/Classes/servers.yaml +++ b/meta/io.murano.applications/Classes/servers.yaml @@ -79,7 +79,7 @@ Methods: .destroy: Body: - - $this.releaseServers($this.items) + - $this.releaseServers($this.servers) getServers: Body: @@ -156,10 +156,6 @@ Methods: - cast($this, ReplicationGroup).deploy() - $this.deployServers($this, $this.items) - .destroy: - Body: - - $this.releaseServers($this.items) - getServers: Body: Return: $.items @@ -197,6 +193,14 @@ Properties: serverNamePattern: Contract: $.string().notNull() + allocated: + Usage: Out + Contract: $.int().notNull() + Default: 0 + + capacity: + Contract: $.int() + Methods: createReplica: Arguments: @@ -205,22 +209,31 @@ Methods: - owner: Contract: $.class(std:Object) Body: - - $template: $this.template - - $template.name: $this.serverNamePattern.format($index) - - $ownerGroup: $this.find(ServerGroup) - - If: $ownerGroup and name($ownerGroup) + - If: $this.capacity = null or $this.allocated < $this.capacity Then: + - $template: $this.template + - $template.name: $this.serverNamePattern.format($index) + - $ownerGroup: $this.find(ServerGroup) + - If: $ownerGroup and name($ownerGroup) + Then: - $groupName: format(' ({0})', name($ownerGroup)) - Else: + Else: - $groupName: '' - - $template['?'].name: format('Server {0}{1}', $index, $groupName) - - Return: new($template, $owner) + - $template['?'].name: format('Server {0}{1}', $index, $groupName) + - $this.allocated: $this.allocated + 1 + - Return: new($template, $owner) + Else: + - Return: null releaseReplicas: Arguments: replicas: Contract: - - $.class(std:Object) + - $.class(res:Instance) Body: - $replicas.select($.beginReleaseResources()) - $replicas.select($.endReleaseResources()) + - $this.allocated: max(0, $this.allocated - len($replicas)) + - Return: [] + + diff --git a/meta/io.murano.applications/Classes/tests/TestReplication.yaml b/meta/io.murano.applications/Classes/tests/TestReplication.yaml index ee917c00..0c1aae13 100644 --- a/meta/io.murano.applications/Classes/tests/TestReplication.yaml +++ b/meta/io.murano.applications/Classes/tests/TestReplication.yaml @@ -93,3 +93,91 @@ Methods: - $.assertEqual(1, len($group.items)) - $.assertEqual(1, $this.provider.allocated) +--- # ------------------------------------------------------------------ # --- + +Name: TestPoolReplicaProvider +Extends: tst:TestFixture + +Methods: + setUp: + Body: + - $this.object1: new(std:Object) + - $this.object2: new(std:Object) + - $this.provider: new(apps:PoolReplicaProvider, pool => [$this.object1, $this.object2]) + + testReplicas: + Body: + - $.assertEqual(2, len($this.provider.pool)) + - $.assertEqual(0, len($this.provider.consumedItems)) + - $obj: $this.provider.createReplica(1, $this) + - $.assertEqual($this.object1, $obj) + - $.assertEqual(2, len($this.provider.pool)) + - $.assertEqual(1, len($this.provider.consumedItems)) + - $obj: $this.provider.createReplica(2, $this) + - $.assertEqual($this.object2, $obj) + - $.assertEqual(2, len($this.provider.pool)) + - $.assertEqual(2, len($this.provider.consumedItems)) + - $obj: $this.provider.createReplica(3, $this) + - $.assertEqual(null, $obj) + - $.assertEqual(2, len($this.provider.pool)) + - $.assertEqual(2, len($this.provider.consumedItems)) + + testReleaseReplicas: + Body: + - $obj: $this.provider.createReplica(1, $this) + - $.assertEqual(1, len($this.provider.consumedItems)) + - $foreignObj: new(std:Object) + - $res: $this.provider.releaseReplicas([$obj, $this.object1, $this.object2, $foreignObj]) + - $.assertEqual(0, len($this.provider.consumedItems)) + - $.assertEqual([$this.object2, $foreignObj], $res) + - $this.testReplicas() + +--- # ------------------------------------------------------------------ # --- + +Name: TestRoundrobinReplicaProvider +Extends: tst:TestFixture + +Methods: + setUp: + Body: + - $this.object1: new(std:Object) + - $this.object2: new(std:Object) + - $this.provider: new(apps:RoundrobinReplicaProvider, items => [$this.object1, $this.object2]) + + testReplicas: + Body: + - $obj: $this.provider.createReplica(1, $this) + - $.assertEqual($this.object1, $obj) + - $obj: $this.provider.createReplica(2, $this) + - $.assertEqual($this.object2, $obj) + - $obj: $this.provider.createReplica(3, $this) + - $.assertEqual($this.object1, $obj) + - $obj: $this.provider.createReplica(4, $this) + - $.assertEqual($this.object2, $obj) + +--- # ------------------------------------------------------------------ # --- + +Name: TestCompositeReplicaProvider +Extends: tst:TestFixture + +Methods: + setUp: + Body: + - $this.objects: range(4).select(new(std:Object)) + - $this.object2: new(std:Object) + - $this.provider1: new(apps:PoolReplicaProvider, pool => [$this.objects[0], $this.objects[1]]) + - $this.provider2: new(apps:RoundrobinReplicaProvider, items => [$this.objects[2], $this.objects[3]]) + - $this.provider: new(apps:CompositeReplicaProvider, providers => [$this.provider1, $this.provider2]) + + testReplicas: + Body: + - $obj: $this.provider.createReplica(1, $this) + - $.assertEqual($this.objects[0], $obj) + - $obj: $this.provider.createReplica(2, $this) + - $.assertEqual($this.objects[1], $obj) + - $obj: $this.provider.createReplica(3, $this) + - $.assertEqual($this.objects[2], $obj) + - $obj: $this.provider.createReplica(4, $this) + - $.assertEqual($this.objects[3], $obj) + - $obj: $this.provider.createReplica(5, $this) + - $.assertEqual($this.objects[2], $obj) diff --git a/meta/io.murano.applications/manifest.yaml b/meta/io.murano.applications/manifest.yaml index b0734dbd..a10a6e9f 100644 --- a/meta/io.murano.applications/manifest.yaml +++ b/meta/io.murano.applications/manifest.yaml @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. -Format: 1.3 +Format: 1.4 Type: Library @@ -27,6 +27,10 @@ Classes: io.murano.applications.ReplicaProvider: replication.yaml io.murano.applications.ReplicationGroup: replication.yaml io.murano.applications.CloneReplicaProvider: replication.yaml + io.murano.applications.CompositeReplicaProvider: replication.yaml + io.murano.applications.PoolReplicaProvider: replication.yaml + io.murano.applications.RoundrobinReplicaProvider: replication.yaml + io.murano.applications.Event: events.yaml io.murano.applications.ServerGroup: servers.yaml @@ -51,6 +55,9 @@ Classes: # Tests io.murano.applications.tests.TestReplication: tests/TestReplication.yaml + io.murano.applications.tests.TestPoolReplicaProvider: tests/TestReplication.yaml + io.murano.applications.tests.TestRoundrobinReplicaProvider: tests/TestReplication.yaml + io.murano.applications.tests.TestCompositeReplicaProvider: tests/TestReplication.yaml io.murano.applications.tests.TestEvents: tests/TestEvents.yaml io.murano.applications.tests.TestMockedServerFactory: tests/TestServerProviders.yaml io.murano.applications.tests.TestSoftwareComponent: tests/TestSoftwareComponent.yaml