-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
250 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package engine | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/laincloud/deployd/storage" | ||
"github.com/mijia/sweb/log" | ||
) | ||
|
||
type IStrategy interface { | ||
Type() string | ||
Rules() []interface{} | ||
} | ||
|
||
type DefaultStrategy struct { | ||
DivType string `json:"Type"` | ||
DivDatas []interface{} `json:"Rule"` | ||
} | ||
|
||
func (ds *DefaultStrategy) Type() string { | ||
return ds.DivType | ||
} | ||
|
||
func (ds *DefaultStrategy) Rules() []interface{} { | ||
return ds.DivDatas | ||
} | ||
|
||
type Canary struct { | ||
Strategies []IStrategy | ||
} | ||
|
||
func (canary *Canary) Equal(nCanary *Canary) bool { | ||
if len(canary.Strategies) != len(nCanary.Strategies) { | ||
return false | ||
} | ||
for i, strategy := range canary.Strategies { | ||
if strategy.Type() != nCanary.Strategies[i].Type() { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
type CanaryPodsWithSpec struct { | ||
PodGroupSpec | ||
canary *Canary | ||
} | ||
|
||
func (spec *CanaryPodsWithSpec) SaveCanary(store storage.Store) error { | ||
key := strings.Join([]string{kLainDeploydRootKey, kLainCanaryKey, spec.Namespace, spec.Name}, "/") | ||
if err := store.Set(key, spec.canary, true); err != nil { | ||
log.Warnf("[Store] Failed to save pod group canary info %s, %s", key, err) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (spec *PodGroupSpec) RemoveCanary(store storage.Store) error { | ||
key := strings.Join([]string{kLainDeploydRootKey, kLainCanaryKey, spec.Namespace, spec.Name}, "/") | ||
if err := store.Remove(key); err != nil { | ||
log.Warnf("[Store] Failed to remove pod group canary info %s, %s", key, err) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (spec *PodGroupSpec) FetchCanary(store storage.Store) (*Canary, error) { | ||
key := strings.Join([]string{kLainDeploydRootKey, kLainCanaryKey, spec.Namespace, spec.Name}, "/") | ||
var canary Canary | ||
if err := store.Get(key, &canary); err != nil { | ||
log.Warnf("[Store] Failed to fetch pod group canary info %s, %s", key, err) | ||
return nil, err | ||
} | ||
return &canary, nil | ||
} | ||
|
||
func (spec *PodGroupSpec) UpdateCanary(store storage.Store, canary *Canary) error { | ||
key := strings.Join([]string{kLainDeploydRootKey, kLainCanaryKey, spec.Namespace, spec.Name}, "/") | ||
if err := store.Set(key, canary, true); err != nil { | ||
log.Warnf("[Store] Failed to update pod group canary info %s, %s", key, err) | ||
return err | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package engine | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestEngineCanaries(t *testing.T) { | ||
etcdAddr := "http://127.0.0.1:2379" | ||
ConfigPortsManager(etcdAddr) | ||
c, store, err := initClusterAndStore() | ||
if err != nil { | ||
t.Fatalf("Cannot create the cluster and storage, %s", err) | ||
} | ||
|
||
engine, err := New(c, store) | ||
if err != nil { | ||
t.Fatalf("Cannot create the orc engine, %s", err) | ||
} | ||
|
||
namespace := "hello" | ||
name := "hello.canary.web" | ||
pgSpec := createPodGroupSpec(namespace, name, 1) | ||
data := map[string]interface{}{"suffix": 1, "upstream": "beta1"} | ||
strategies := []IStrategy{&DefaultStrategy{"uidsuffix", []interface{}{data}}} | ||
canary := &Canary{strategies} | ||
canarySpec := CanaryPodsWithSpec{pgSpec, canary} | ||
if err := engine.NewCanary(canarySpec); err != nil { | ||
t.Fatalf("Should not return error, %s", err) | ||
} | ||
if err := engine.NewCanary(canarySpec); err == nil { | ||
t.Errorf("Should return exists error, but we got no problem") | ||
} | ||
|
||
time.Sleep(20 * time.Second) | ||
if pg, ok := engine.InspectPodGroup(name); !ok { | ||
t.Errorf("We should have the pod group, but we don't get it") | ||
} else if pg.State != RunStateSuccess { | ||
t.Errorf("We should have the pod deployed and running") | ||
} | ||
|
||
engine.RescheduleInstance(name, 3) | ||
time.Sleep(20 * time.Second) | ||
if pg, ok := engine.InspectPodGroup(name); !ok { | ||
t.Errorf("We should have the pod group, but we don't get it") | ||
} else if len(pg.Pods) != 3 { | ||
t.Errorf("We should have 3 instance of the pods") | ||
} | ||
|
||
engine.RescheduleInstance(name, 1) | ||
time.Sleep(30 * time.Second) | ||
if pg, ok := engine.InspectPodGroup(name); !ok { | ||
t.Errorf("We should have the pod group, but we don't get it") | ||
} else if len(pg.Pods) != 1 { | ||
bytes, err := json.Marshal(pg.Pods) | ||
pods := "" | ||
if err == nil { | ||
pods = string(bytes) | ||
} | ||
t.Errorf("We should have 1 instance of the pods : %v", pods) | ||
} | ||
|
||
podSpec := createPodSpec(namespace, name) | ||
podSpec.Containers[0].MemoryLimit = 24 * 1024 * 1024 | ||
engine.RescheduleSpec(name, podSpec) | ||
time.Sleep(40 * time.Second) | ||
if pg, ok := engine.InspectPodGroup(name); !ok { | ||
t.Errorf("We should have the pod group, but we don't get it") | ||
} else if pg.Spec.Version != 1 { | ||
t.Errorf("We should have version 1 of the pods") | ||
} | ||
|
||
if nCanary := engine.FetchCanaryInfos(name); nCanary == nil { | ||
t.Fatalf("Should return canary!") | ||
} else { | ||
if !nCanary.Equal(canary) { | ||
t.Fatalf("Canary info should not changed") | ||
} | ||
} | ||
|
||
if err := engine.RemovePodGroup(name); err != nil { | ||
t.Errorf("We should be able to remove the pod group, %s", err) | ||
} else if err := engine.NewPodGroup(pgSpec); err == nil { | ||
t.Errorf("We should not be able to deploy pod group again in short time we remove it") | ||
} | ||
time.Sleep(20 * time.Second) | ||
|
||
if nCanary := engine.FetchCanaryInfos(name); nCanary != nil { | ||
t.Fatalf("Should not return nCanary") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters