Skip to content

Commit

Permalink
Merge pull request #265 from istalker2/void-resource
Browse files Browse the repository at this point in the history
'void' pseudo resource type
  • Loading branch information
pigmej authored Jun 9, 2017
2 parents 56cfbf2 + dd30a19 commit 437b0eb
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 1 deletion.
1 change: 1 addition & 0 deletions pkg/resources/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func init() {
serviceTemplateFactory{},
serviceAccountTemplateFactory{},
statefulSetTemplateFactory{},
voidTemplateFactory{},
}
for _, factory := range factories {
KindToResourceTemplate[factory.Kind()] = factory
Expand Down
69 changes: 69 additions & 0 deletions pkg/resources/void.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2017 Mirantis
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package resources

import (
"github.com/Mirantis/k8s-AppController/pkg/client"
"github.com/Mirantis/k8s-AppController/pkg/interfaces"
"github.com/Mirantis/k8s-AppController/pkg/report"
)

type void struct {
Base
name string
}

type voidTemplateFactory struct{}

// Returns wrapped resource name. Since void resource cannot be wrapped it is always empty string
func (voidTemplateFactory) ShortName(_ client.ResourceDefinition) string {
return ""
}

// k8s resource kind that this fabric supports
func (voidTemplateFactory) Kind() string {
return "void"
}

// New returns new void based on resource definition. Since void cannot be wrapped it is always nil
func (voidTemplateFactory) New(_ client.ResourceDefinition, _ client.Interface, _ interfaces.GraphContext) interfaces.Resource {
return nil
}

// NewExisting returns new void with specified name
func (voidTemplateFactory) NewExisting(name string, _ client.Interface, gc interfaces.GraphContext) interfaces.Resource {
name = parametrizeResource(name, gc, []string{"*"}).(string)
return report.SimpleReporter{BaseResource: void{name: name}}
}

// Key returns void name
func (v void) Key() string {
return "void/" + v.name
}

// Status always returns "ready"
func (void) Status(_ map[string]string) (interfaces.ResourceStatus, error) {
return interfaces.ResourceReady, nil
}

// Delete is a no-op method to create resource
func (void) Create() error {
return nil
}

// Delete is a no-op method to delete resource
func (void) Delete() error {
return nil
}
40 changes: 40 additions & 0 deletions pkg/scheduler/flows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1327,3 +1327,43 @@ func TestMultipathParameterPassingWithSuffix(t *testing.T) {
t.Errorf("not all jobs were created: %d jobs were not found", len(jobNames))
}
}

// TestSyncOnVoidResource tests replica deployment synchronization on void resource - pods from all replicas must be
// created before the first job deployment begins. Void acts here as a sync point because it dose nothing but is shared
// by all replicas and thus depends on parents (pods) from all replicas
func TestSyncOnVoidResource(t *testing.T) {
replicaCount := 5
c, fake := mocks.NewClientWithFake(
mocks.MakeFlow("test"),
mocks.MakeResourceDefinition("pod/ready-$AC_NAME"),
mocks.MakeResourceDefinition("job/ready-$AC_NAME"),
mocks.MakeDependency("flow/test", "pod/ready-$AC_NAME", "flow=test"),
mocks.MakeDependency("pod/ready-$AC_NAME", "void/checkpoint", "flow=test"),
mocks.MakeDependency("void/checkpoint", "job/ready-$AC_NAME", "flow=test"),
)

stopChan := make(chan struct{})
podCount := 0

fake.PrependReactor("create", "*",
func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) {
switch action.GetResource().Resource {
case "pods":
podCount++
case "jobs":
if podCount != replicaCount {
t.Errorf("expected %d pods to exist, found %d", replicaCount, podCount)
}
}
return false, nil, nil
})

depGraph, err := New(c, nil, 0).BuildDependencyGraph(
interfaces.DependencyGraphOptions{ReplicaCount: replicaCount, FlowName: "test"})
if err != nil {
t.Fatal(err)
}

depGraph.Deploy(stopChan)
ensureReplicas(c, t, replicaCount, replicaCount)
}
1 change: 0 additions & 1 deletion pkg/scheduler/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,6 @@ func createResources(toCreate chan *ScheduledResource, finished chan string, ccL
req := r.context.graph.graph[reqKey]
go func(req *ScheduledResource, toCreate chan *ScheduledResource) {
ticker := time.NewTicker(CheckInterval)
log.Printf("Requesting creation of dependency %v", req.Key())
for {
select {
case <-stopChan:
Expand Down

0 comments on commit 437b0eb

Please sign in to comment.