mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
pkg/controller: add unit test for daemonset target
This commit is contained in:
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
daemonSetScaleDownNodeSelector = map[string]string{"flux.weave.works/non-exist": "true"}
|
||||
daemonSetScaleDownNodeSelector = map[string]string{"flagger.weave.works/non-exist": "true"}
|
||||
)
|
||||
|
||||
// DaemonSetController is managing the operations for Kubernetes DaemonSet kind
|
||||
|
||||
@@ -204,40 +204,6 @@ func newDaemonSetControllerTestCanary() *flaggerv1.Canary {
|
||||
return cd
|
||||
}
|
||||
|
||||
/*func newDaemonSetControllerWithout() *appsv1.DaemonSet {
|
||||
n := "nginx-without-node-selector"
|
||||
d := &appsv1.DaemonSet{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: n,
|
||||
},
|
||||
Spec: appsv1.DaemonSetSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"name": n,
|
||||
},
|
||||
},
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"name": n,
|
||||
},
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: n,
|
||||
Image: "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return d
|
||||
}
|
||||
*/
|
||||
func newDaemonSetControllerTestPodInfo() *appsv1.DaemonSet {
|
||||
d := &appsv1.DaemonSet{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
|
||||
@@ -222,7 +222,7 @@ func (c *Controller) syncHandler(key string) error {
|
||||
|
||||
// set status condition for new canaries
|
||||
if cd.Status.Conditions == nil {
|
||||
if ok, conditions := canary.MakeStatusConditions(cd.Status, flaggerv1.CanaryPhaseInitializing); ok {
|
||||
if ok, conditions := canary.MakeStatusConditions(cd, flaggerv1.CanaryPhaseInitializing); ok {
|
||||
cdCopy := cd.DeepCopy()
|
||||
cdCopy.Status.Conditions = conditions
|
||||
cdCopy.Status.LastTransitionTime = metav1.Now()
|
||||
|
||||
@@ -116,7 +116,7 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
|
||||
return
|
||||
}
|
||||
|
||||
// create primary deployment and hpa
|
||||
// create primary
|
||||
err = canaryController.Initialize(cd, skipLivenessChecks)
|
||||
if err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
@@ -161,7 +161,7 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
|
||||
maxWeight = cd.Spec.CanaryAnalysis.MaxWeight
|
||||
}
|
||||
|
||||
// check primary deployment status
|
||||
// check primary status
|
||||
if !skipLivenessChecks && !cd.Spec.SkipAnalysis {
|
||||
if _, err := canaryController.IsPrimaryReady(cd); err != nil {
|
||||
c.recordEventWarningf(cd, "%v", err)
|
||||
@@ -210,7 +210,7 @@ func (c *Controller) advanceCanary(name string, namespace string, skipLivenessCh
|
||||
return
|
||||
}
|
||||
|
||||
// check canary deployment status
|
||||
// check canary status
|
||||
var retriable = true
|
||||
if !skipLivenessChecks {
|
||||
retriable, err = canaryController.IsCanaryReady(cd)
|
||||
@@ -617,7 +617,7 @@ func (c *Controller) checkCanaryStatus(canary *flaggerv1.Canary, canaryControlle
|
||||
}
|
||||
c.recorder.SetStatus(canary, flaggerv1.CanaryPhaseInitialized)
|
||||
c.recordEventInfof(canary, "Initialization done! %s.%s", canary.Name, canary.Namespace)
|
||||
c.alert(canary, "New deployment detected, initialization completed.",
|
||||
c.alert(canary, fmt.Sprintf("New %s detected, initialization completed.", canary.Spec.TargetRef.Kind),
|
||||
true, flaggerv1.SeverityInfo)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package controller
|
||||
|
||||
func alwaysReady() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func toFloatPtr(val int) *float64 {
|
||||
v := float64(val)
|
||||
return &v
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/weaveworks/flagger/pkg/metrics/observers"
|
||||
|
||||
"go.uber.org/zap"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
|
||||
flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1"
|
||||
istiov1alpha1 "github.com/weaveworks/flagger/pkg/apis/istio/common/v1alpha1"
|
||||
istiov1alpha3 "github.com/weaveworks/flagger/pkg/apis/istio/v1alpha3"
|
||||
"github.com/weaveworks/flagger/pkg/canary"
|
||||
clientset "github.com/weaveworks/flagger/pkg/client/clientset/versioned"
|
||||
fakeFlagger "github.com/weaveworks/flagger/pkg/client/clientset/versioned/fake"
|
||||
informers "github.com/weaveworks/flagger/pkg/client/informers/externalversions"
|
||||
"github.com/weaveworks/flagger/pkg/logger"
|
||||
"github.com/weaveworks/flagger/pkg/metrics"
|
||||
"github.com/weaveworks/flagger/pkg/router"
|
||||
)
|
||||
|
||||
type daemonSetFixture struct {
|
||||
canary *flaggerv1.Canary
|
||||
kubeClient kubernetes.Interface
|
||||
meshClient clientset.Interface
|
||||
flaggerClient clientset.Interface
|
||||
deployer canary.Controller
|
||||
ctrl *Controller
|
||||
logger *zap.SugaredLogger
|
||||
router router.Interface
|
||||
}
|
||||
|
||||
func newDaemonSetFixture(c *flaggerv1.Canary) daemonSetFixture {
|
||||
if c == nil {
|
||||
c = newDaemonSetTestCanary()
|
||||
}
|
||||
|
||||
// init Flagger clientset and register objects
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(
|
||||
c,
|
||||
newDaemonSetTestMetricTemplate(),
|
||||
newDaemonSetTestAlertProvider(),
|
||||
)
|
||||
|
||||
// init Kubernetes clientset and register objects
|
||||
kubeClient := fake.NewSimpleClientset(
|
||||
newDaemonSetTestDaemonSet(),
|
||||
newDaemonSetTestService(),
|
||||
newDaemonSetTestConfigMap(),
|
||||
newDaemonSetTestConfigMapEnv(),
|
||||
newDaemonSetTestConfigMapVol(),
|
||||
newDaemonSetTestSecret(),
|
||||
newDaemonSetTestSecretEnv(),
|
||||
newDaemonSetTestSecretVol(),
|
||||
newDaemonSetTestAlertProviderSecret(),
|
||||
)
|
||||
|
||||
logger, _ := logger.NewLogger("debug")
|
||||
|
||||
// init controller
|
||||
flaggerInformerFactory := informers.NewSharedInformerFactory(flaggerClient, 0)
|
||||
|
||||
fi := Informers{
|
||||
CanaryInformer: flaggerInformerFactory.Flagger().V1beta1().Canaries(),
|
||||
MetricInformer: flaggerInformerFactory.Flagger().V1beta1().MetricTemplates(),
|
||||
AlertInformer: flaggerInformerFactory.Flagger().V1beta1().AlertProviders(),
|
||||
}
|
||||
|
||||
// init router
|
||||
rf := router.NewFactory(nil, kubeClient, flaggerClient, "annotationsPrefix", logger, flaggerClient)
|
||||
|
||||
// init observer
|
||||
observerFactory, _ := observers.NewFactory("fake")
|
||||
|
||||
// init canary factory
|
||||
configTracker := &canary.ConfigTracker{
|
||||
Logger: logger,
|
||||
KubeClient: kubeClient,
|
||||
FlaggerClient: flaggerClient,
|
||||
}
|
||||
canaryFactory := canary.NewFactory(kubeClient, flaggerClient, configTracker, []string{"app", "name"}, logger)
|
||||
|
||||
ctrl := &Controller{
|
||||
kubeClient: kubeClient,
|
||||
istioClient: flaggerClient,
|
||||
flaggerClient: flaggerClient,
|
||||
flaggerInformers: fi,
|
||||
flaggerSynced: fi.CanaryInformer.Informer().HasSynced,
|
||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), controllerAgentName),
|
||||
eventRecorder: &record.FakeRecorder{},
|
||||
logger: logger,
|
||||
canaries: new(sync.Map),
|
||||
flaggerWindow: time.Second,
|
||||
canaryFactory: canaryFactory,
|
||||
observerFactory: observerFactory,
|
||||
recorder: metrics.NewRecorder(controllerAgentName, false),
|
||||
routerFactory: rf,
|
||||
}
|
||||
ctrl.flaggerSynced = alwaysReady
|
||||
ctrl.flaggerInformers.CanaryInformer.Informer().GetIndexer().Add(c)
|
||||
ctrl.flaggerInformers.MetricInformer.Informer().GetIndexer().Add(newDaemonSetTestMetricTemplate())
|
||||
ctrl.flaggerInformers.AlertInformer.Informer().GetIndexer().Add(newDaemonSetTestAlertProvider())
|
||||
|
||||
meshRouter := rf.MeshRouter("istio")
|
||||
|
||||
return daemonSetFixture{
|
||||
canary: c,
|
||||
deployer: canaryFactory.Controller("DaemonSet"),
|
||||
logger: logger,
|
||||
flaggerClient: flaggerClient,
|
||||
meshClient: flaggerClient,
|
||||
kubeClient: kubeClient,
|
||||
ctrl: ctrl,
|
||||
router: meshRouter,
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestConfigMap() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-config-env",
|
||||
},
|
||||
Data: map[string]string{
|
||||
"color": "red",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestConfigMapV2() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-config-env",
|
||||
},
|
||||
Data: map[string]string{
|
||||
"color": "blue",
|
||||
"output": "console",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestConfigMapEnv() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-config-all-env",
|
||||
},
|
||||
Data: map[string]string{
|
||||
"color": "red",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestConfigMapVol() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-config-vol",
|
||||
},
|
||||
Data: map[string]string{
|
||||
"color": "red",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestSecret() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-secret-env",
|
||||
},
|
||||
Type: corev1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
"apiKey": []byte("test"),
|
||||
"username": []byte("test"),
|
||||
"password": []byte("test"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestSecretV2() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-secret-env",
|
||||
},
|
||||
Type: corev1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
"apiKey": []byte("test2"),
|
||||
"username": []byte("test"),
|
||||
"password": []byte("test"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestSecretEnv() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-secret-all-env",
|
||||
},
|
||||
Type: corev1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
"apiKey": []byte("test"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestSecretVol() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-secret-vol",
|
||||
},
|
||||
Type: corev1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
"apiKey": []byte("test"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestCanary() *flaggerv1.Canary {
|
||||
cd := &flaggerv1.Canary{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: flaggerv1.CanarySpec{
|
||||
TargetRef: flaggerv1.CrossNamespaceObjectReference{
|
||||
Name: "podinfo",
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "DaemonSet",
|
||||
}, Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
StepWeight: 10,
|
||||
MaxWeight: 50,
|
||||
Metrics: []flaggerv1.CanaryMetric{
|
||||
{
|
||||
Name: "request-success-rate",
|
||||
Threshold: 99,
|
||||
Interval: "1m",
|
||||
},
|
||||
{
|
||||
Name: "request-duration",
|
||||
ThresholdRange: &flaggerv1.CanaryThresholdRange{
|
||||
Min: toFloatPtr(0),
|
||||
Max: toFloatPtr(500000),
|
||||
},
|
||||
Interval: "1m",
|
||||
},
|
||||
{
|
||||
Name: "custom",
|
||||
ThresholdRange: &flaggerv1.CanaryThresholdRange{
|
||||
Min: toFloatPtr(0),
|
||||
Max: toFloatPtr(100),
|
||||
},
|
||||
Interval: "1m",
|
||||
TemplateRef: &flaggerv1.CrossNamespaceObjectReference{
|
||||
Name: "envoy",
|
||||
Namespace: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return cd
|
||||
}
|
||||
|
||||
func newDaemonSetTestCanaryMirror() *flaggerv1.Canary {
|
||||
cd := newDaemonSetTestCanary()
|
||||
cd.Spec.CanaryAnalysis.Mirror = true
|
||||
return cd
|
||||
}
|
||||
|
||||
func newDaemonSetTestCanaryAB() *flaggerv1.Canary {
|
||||
cd := &flaggerv1.Canary{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: flaggerv1.CanarySpec{
|
||||
TargetRef: flaggerv1.CrossNamespaceObjectReference{
|
||||
Name: "podinfo",
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "DaemonSet",
|
||||
}, Service: flaggerv1.CanaryService{
|
||||
Port: 9898,
|
||||
}, CanaryAnalysis: flaggerv1.CanaryAnalysis{
|
||||
Threshold: 10,
|
||||
Iterations: 10,
|
||||
Match: []istiov1alpha3.HTTPMatchRequest{
|
||||
{
|
||||
Headers: map[string]istiov1alpha1.StringMatch{
|
||||
"x-user-type": {
|
||||
Exact: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Metrics: []flaggerv1.CanaryMetric{
|
||||
{
|
||||
Name: "request-success-rate",
|
||||
ThresholdRange: &flaggerv1.CanaryThresholdRange{
|
||||
Min: toFloatPtr(99),
|
||||
Max: toFloatPtr(100),
|
||||
},
|
||||
Interval: "1m",
|
||||
},
|
||||
{
|
||||
Name: "request-duration",
|
||||
Threshold: 500000,
|
||||
Interval: "1m",
|
||||
},
|
||||
{
|
||||
Name: "custom",
|
||||
ThresholdRange: &flaggerv1.CanaryThresholdRange{
|
||||
Min: toFloatPtr(0),
|
||||
Max: toFloatPtr(500000),
|
||||
},
|
||||
Interval: "1m",
|
||||
Query: "fake",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return cd
|
||||
}
|
||||
|
||||
func newDaemonSetTestDaemonSet() *appsv1.DaemonSet {
|
||||
d := &appsv1.DaemonSet{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: appsv1.DaemonSetSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
},
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "podinfo",
|
||||
Image: "quay.io/stefanprodan/podinfo:1.2.0",
|
||||
Command: []string{
|
||||
"./podinfo",
|
||||
"--port=9898",
|
||||
},
|
||||
Args: nil,
|
||||
WorkingDir: "",
|
||||
Ports: []corev1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: 9898,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
Name: "http-metrics",
|
||||
ContainerPort: 8080,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
},
|
||||
{
|
||||
ContainerPort: 8888,
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "PODINFO_UI_COLOR",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-config-env",
|
||||
},
|
||||
Key: "color",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "API_KEY",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-secret-env",
|
||||
},
|
||||
Key: "apiKey",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-config-all-env",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
SecretRef: &corev1.SecretEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-secret-all-env",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "config",
|
||||
MountPath: "/etc/podinfo/config",
|
||||
ReadOnly: true,
|
||||
},
|
||||
{
|
||||
Name: "secret",
|
||||
MountPath: "/etc/podinfo/secret",
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "config",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-config-vol",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "secret",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: "podinfo-secret-vol",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func newDaemonSetTestDaemonSetV2() *appsv1.DaemonSet {
|
||||
d := &appsv1.DaemonSet{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: appsv1.DaemonSetSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
},
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "podinfo",
|
||||
Image: "quay.io/stefanprodan/podinfo:1.2.1",
|
||||
Ports: []corev1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: 9898,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
Command: []string{
|
||||
"./podinfo",
|
||||
"--port=9898",
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "PODINFO_UI_COLOR",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-config-env",
|
||||
},
|
||||
Key: "color",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "API_KEY",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-secret-env",
|
||||
},
|
||||
Key: "apiKey",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-config-all-env",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "config",
|
||||
MountPath: "/etc/podinfo/config",
|
||||
ReadOnly: true,
|
||||
},
|
||||
{
|
||||
Name: "secret",
|
||||
MountPath: "/etc/podinfo/secret",
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "config",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-config-vol",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "secret",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Secret: &corev1.SecretVolumeSource{
|
||||
SecretName: "podinfo-secret-vol",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func newDaemonSetTestService() *corev1.Service {
|
||||
d := &corev1.Service{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Selector: map[string]string{
|
||||
"app": "podinfo",
|
||||
},
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Port: 9898,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
TargetPort: intstr.FromString("http"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func newDaemonSetTestServiceV2() *corev1.Service {
|
||||
d := &corev1.Service{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: corev1.ServiceSpec{
|
||||
Selector: map[string]string{
|
||||
"app": "podinfo-v2",
|
||||
},
|
||||
Type: corev1.ServiceTypeClusterIP,
|
||||
Ports: []corev1.ServicePort{
|
||||
{
|
||||
Name: "http",
|
||||
Port: 9898,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
TargetPort: intstr.FromString("http"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func newDaemonSetTestMetricTemplate() *flaggerv1.MetricTemplate {
|
||||
provider := flaggerv1.MetricTemplateProvider{
|
||||
Type: "prometheus",
|
||||
Address: "fake",
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "podinfo-secret-env",
|
||||
},
|
||||
}
|
||||
|
||||
template := &flaggerv1.MetricTemplate{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "envoy",
|
||||
},
|
||||
Spec: flaggerv1.MetricTemplateSpec{
|
||||
Provider: provider,
|
||||
Query: `sum(envoy_cluster_upstream_rq{envoy_cluster_name=~"{{ namespace }}_{{ target }}"})`,
|
||||
},
|
||||
}
|
||||
return template
|
||||
}
|
||||
|
||||
func newDaemonSetTestAlertProviderSecret() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "alert-secret",
|
||||
},
|
||||
Type: corev1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
"address": []byte("http://mock.slack"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDaemonSetTestAlertProvider() *flaggerv1.AlertProvider {
|
||||
return &flaggerv1.AlertProvider{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "slack",
|
||||
},
|
||||
Spec: flaggerv1.AlertProviderSpec{
|
||||
Type: "slack",
|
||||
Address: "http://fake.slack",
|
||||
SecretRef: &corev1.LocalObjectReference{
|
||||
Name: "alert-secret",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,678 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
|
||||
flaggerv1 "github.com/weaveworks/flagger/pkg/apis/flagger/v1beta1"
|
||||
"github.com/weaveworks/flagger/pkg/notifier"
|
||||
)
|
||||
|
||||
func TestScheduler_DaemonSetInit(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
_, err := mocks.kubeClient.AppsV1().DaemonSets("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetNewRevision(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// update
|
||||
dep2 := newDaemonSetTestDaemonSetV2()
|
||||
_, err := mocks.kubeClient.AppsV1().DaemonSets("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
_, err = mocks.kubeClient.AppsV1().DaemonSets("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetRollback(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// update failed checks to max
|
||||
err := mocks.deployer.SyncStatus(mocks.canary, flaggerv1.CanaryStatus{Phase: flaggerv1.CanaryPhaseProgressing, FailedChecks: 10})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// set a metric check to fail
|
||||
c, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
cd := c.DeepCopy()
|
||||
cd.Spec.CanaryAnalysis.Metrics = append(c.Spec.CanaryAnalysis.Metrics, flaggerv1.CanaryMetric{
|
||||
Name: "fail",
|
||||
Interval: "1m",
|
||||
ThresholdRange: &flaggerv1.CanaryThresholdRange{
|
||||
Min: toFloatPtr(0),
|
||||
Max: toFloatPtr(50),
|
||||
},
|
||||
Query: "fail",
|
||||
})
|
||||
_, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(cd)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// run metric checks
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// finalise analysis
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check status
|
||||
c, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhaseFailed {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhaseFailed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetSkipAnalysis(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// enable skip
|
||||
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
cd.Spec.SkipAnalysis = true
|
||||
_, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(cd)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// update
|
||||
dep2 := newDaemonSetTestDaemonSetV2()
|
||||
_, err = mocks.kubeClient.AppsV1().DaemonSets("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
// advance
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
c, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
if !c.Spec.SkipAnalysis {
|
||||
t.Errorf("Got skip analysis %v wanted %v", c.Spec.SkipAnalysis, true)
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhaseSucceeded {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhaseSucceeded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetNewRevisionReset(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// first update
|
||||
dep2 := newDaemonSetTestDaemonSetV2()
|
||||
_, err := mocks.kubeClient.AppsV1().DaemonSets("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
// advance
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
primaryWeight, canaryWeight, mirrored, err := mocks.router.GetRoutes(mocks.canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if primaryWeight != 90 {
|
||||
t.Errorf("Got primary route %v wanted %v", primaryWeight, 90)
|
||||
}
|
||||
|
||||
if canaryWeight != 10 {
|
||||
t.Errorf("Got canary route %v wanted %v", canaryWeight, 10)
|
||||
}
|
||||
|
||||
if mirrored != false {
|
||||
t.Errorf("Got mirrored %v wanted %v", mirrored, false)
|
||||
}
|
||||
|
||||
// second update
|
||||
dep2.Spec.Template.Spec.ServiceAccountName = "test"
|
||||
_, err = mocks.kubeClient.AppsV1().DaemonSets("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
primaryWeight, canaryWeight, mirrored, err = mocks.router.GetRoutes(mocks.canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if primaryWeight != 100 {
|
||||
t.Errorf("Got primary route %v wanted %v", primaryWeight, 100)
|
||||
}
|
||||
|
||||
if canaryWeight != 0 {
|
||||
t.Errorf("Got canary route %v wanted %v", canaryWeight, 0)
|
||||
}
|
||||
|
||||
if mirrored != false {
|
||||
t.Errorf("Got mirrored %v wanted %v", mirrored, false)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetPromotion(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check initialized status
|
||||
c, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhaseInitialized {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhaseInitialized)
|
||||
}
|
||||
|
||||
// update
|
||||
dep2 := newDaemonSetTestDaemonSetV2()
|
||||
_, err = mocks.kubeClient.AppsV1().DaemonSets("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect pod spec changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
config2 := newDaemonSetTestConfigMapV2()
|
||||
_, err = mocks.kubeClient.CoreV1().ConfigMaps("default").Update(config2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
secret2 := newDaemonSetTestSecretV2()
|
||||
_, err = mocks.kubeClient.CoreV1().Secrets("default").Update(secret2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect configs changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
primaryWeight, canaryWeight, mirrored, err := mocks.router.GetRoutes(mocks.canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
primaryWeight = 60
|
||||
canaryWeight = 40
|
||||
err = mocks.router.SetRoutes(mocks.canary, primaryWeight, canaryWeight, mirrored)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// advance
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check progressing status
|
||||
c, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhaseProgressing {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhaseProgressing)
|
||||
}
|
||||
|
||||
// promote
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check promoting status
|
||||
c, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhasePromoting {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhasePromoting)
|
||||
}
|
||||
|
||||
// finalise
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
primaryWeight, canaryWeight, mirrored, err = mocks.router.GetRoutes(mocks.canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if primaryWeight != 100 {
|
||||
t.Errorf("Got primary route %v wanted %v", primaryWeight, 100)
|
||||
}
|
||||
|
||||
if canaryWeight != 0 {
|
||||
t.Errorf("Got canary route %v wanted %v", canaryWeight, 0)
|
||||
}
|
||||
|
||||
if mirrored != false {
|
||||
t.Errorf("Got mirrored %v wanted %v", mirrored, false)
|
||||
}
|
||||
|
||||
primaryDep, err := mocks.kubeClient.AppsV1().DaemonSets("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
primaryImage := primaryDep.Spec.Template.Spec.Containers[0].Image
|
||||
canaryImage := dep2.Spec.Template.Spec.Containers[0].Image
|
||||
if primaryImage != canaryImage {
|
||||
t.Errorf("Got primary image %v wanted %v", primaryImage, canaryImage)
|
||||
}
|
||||
|
||||
configPrimary, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get("podinfo-config-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if configPrimary.Data["color"] != config2.Data["color"] {
|
||||
t.Errorf("Got primary ConfigMap color %s wanted %s", configPrimary.Data["color"], config2.Data["color"])
|
||||
}
|
||||
|
||||
secretPrimary, err := mocks.kubeClient.CoreV1().Secrets("default").Get("podinfo-secret-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if string(secretPrimary.Data["apiKey"]) != string(secret2.Data["apiKey"]) {
|
||||
t.Errorf("Got primary secret %s wanted %s", secretPrimary.Data["apiKey"], secret2.Data["apiKey"])
|
||||
}
|
||||
|
||||
// check finalising status
|
||||
c, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhaseFinalising {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhaseFinalising)
|
||||
}
|
||||
|
||||
// scale canary to zero
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
c, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhaseSucceeded {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhaseSucceeded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetMirroring(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(newDaemonSetTestCanaryMirror())
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// update
|
||||
dep2 := newDaemonSetTestDaemonSetV2()
|
||||
_, err := mocks.kubeClient.AppsV1().DaemonSets("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect pod spec changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// advance
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check if traffic is mirrored to canary
|
||||
primaryWeight, canaryWeight, mirrored, err := mocks.router.GetRoutes(mocks.canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if primaryWeight != 100 {
|
||||
t.Errorf("Got primary route %v wanted %v", primaryWeight, 100)
|
||||
}
|
||||
|
||||
if canaryWeight != 0 {
|
||||
t.Errorf("Got canary route %v wanted %v", canaryWeight, 0)
|
||||
}
|
||||
|
||||
if mirrored != true {
|
||||
t.Errorf("Got mirrored %v wanted %v", mirrored, true)
|
||||
}
|
||||
|
||||
// advance
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check if traffic is mirrored to canary
|
||||
primaryWeight, canaryWeight, mirrored, err = mocks.router.GetRoutes(mocks.canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if primaryWeight != 90 {
|
||||
t.Errorf("Got primary route %v wanted %v", primaryWeight, 90)
|
||||
}
|
||||
|
||||
if canaryWeight != 10 {
|
||||
t.Errorf("Got canary route %v wanted %v", canaryWeight, 10)
|
||||
}
|
||||
|
||||
if mirrored != false {
|
||||
t.Errorf("Got mirrored %v wanted %v", mirrored, false)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetABTesting(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(newDaemonSetTestCanaryAB())
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// update
|
||||
dep2 := newDaemonSetTestDaemonSetV2()
|
||||
_, err := mocks.kubeClient.AppsV1().DaemonSets("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// detect pod spec changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// advance
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check if traffic is routed to canary
|
||||
primaryWeight, canaryWeight, mirrored, err := mocks.router.GetRoutes(mocks.canary)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if primaryWeight != 0 {
|
||||
t.Errorf("Got primary route %v wanted %v", primaryWeight, 0)
|
||||
}
|
||||
|
||||
if canaryWeight != 100 {
|
||||
t.Errorf("Got canary route %v wanted %v", canaryWeight, 100)
|
||||
}
|
||||
|
||||
if mirrored != false {
|
||||
t.Errorf("Got mirrored %v wanted %v", mirrored, false)
|
||||
}
|
||||
|
||||
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// set max iterations
|
||||
if err := mocks.deployer.SetStatusIterations(cd, 10); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// advance
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// finalising
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check finalising status
|
||||
c, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhaseFinalising {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhaseFinalising)
|
||||
}
|
||||
|
||||
// check if the container image tag was updated
|
||||
primaryDep, err := mocks.kubeClient.AppsV1().DaemonSets("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
primaryImage := primaryDep.Spec.Template.Spec.Containers[0].Image
|
||||
canaryImage := dep2.Spec.Template.Spec.Containers[0].Image
|
||||
if primaryImage != canaryImage {
|
||||
t.Errorf("Got primary image %v wanted %v", primaryImage, canaryImage)
|
||||
}
|
||||
|
||||
// shutdown canary
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// check rollout status
|
||||
c, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if c.Status.Phase != flaggerv1.CanaryPhaseSucceeded {
|
||||
t.Errorf("Got canary state %v wanted %v", c.Status.Phase, flaggerv1.CanaryPhaseSucceeded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetPortDiscovery(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
|
||||
// enable port discovery
|
||||
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
cd.Spec.Service.PortDiscovery = true
|
||||
_, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(cd)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
canarySvc, err := mocks.kubeClient.CoreV1().Services("default").Get("podinfo-canary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if len(canarySvc.Spec.Ports) != 3 {
|
||||
t.Fatalf("Got svc port count %v wanted %v", len(canarySvc.Spec.Ports), 3)
|
||||
}
|
||||
|
||||
matchPorts := func(lookup string) bool {
|
||||
switch lookup {
|
||||
case
|
||||
"http 9898",
|
||||
"http-metrics 8080",
|
||||
"tcp-podinfo-2 8888":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, port := range canarySvc.Spec.Ports {
|
||||
if !matchPorts(fmt.Sprintf("%s %v", port.Name, port.Port)) {
|
||||
t.Fatalf("Got wrong svc port %v", port.Name)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetTargetPortNumber(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
|
||||
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
cd.Spec.Service.Port = 80
|
||||
cd.Spec.Service.TargetPort = intstr.FromInt(9898)
|
||||
cd.Spec.Service.PortDiscovery = true
|
||||
_, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(cd)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
canarySvc, err := mocks.kubeClient.CoreV1().Services("default").Get("podinfo-canary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if len(canarySvc.Spec.Ports) != 3 {
|
||||
t.Fatalf("Got svc port count %v wanted %v", len(canarySvc.Spec.Ports), 3)
|
||||
}
|
||||
|
||||
matchPorts := func(lookup string) bool {
|
||||
switch lookup {
|
||||
case
|
||||
"http 80",
|
||||
"http-metrics 8080",
|
||||
"tcp-podinfo-2 8888":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, port := range canarySvc.Spec.Ports {
|
||||
if !matchPorts(fmt.Sprintf("%s %v", port.Name, port.Port)) {
|
||||
t.Fatalf("Got wrong svc port %v", port.Name)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetTargetPortName(t *testing.T) {
|
||||
mocks := newDaemonSetFixture(nil)
|
||||
|
||||
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
cd.Spec.Service.Port = 8080
|
||||
cd.Spec.Service.TargetPort = intstr.FromString("http")
|
||||
cd.Spec.Service.PortDiscovery = true
|
||||
_, err = mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Update(cd)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
canarySvc, err := mocks.kubeClient.CoreV1().Services("default").Get("podinfo-canary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if len(canarySvc.Spec.Ports) != 3 {
|
||||
t.Fatalf("Got svc port count %v wanted %v", len(canarySvc.Spec.Ports), 3)
|
||||
}
|
||||
|
||||
matchPorts := func(lookup string) bool {
|
||||
switch lookup {
|
||||
case
|
||||
"http 8080",
|
||||
"http-metrics 8080",
|
||||
"tcp-podinfo-2 8888":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, port := range canarySvc.Spec.Ports {
|
||||
if !matchPorts(fmt.Sprintf("%s %v", port.Name, port.Port)) {
|
||||
t.Fatalf("Got wrong svc port %v", port.Name)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_DaemonSetAlerts(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var payload = notifier.SlackPayload{}
|
||||
err = json.Unmarshal(b, &payload)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if payload.Attachments[0].AuthorName != "podinfo.default" {
|
||||
t.Fatal("wrong author name")
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
canary := newDaemonSetTestCanary()
|
||||
canary.Spec.CanaryAnalysis.Alerts = []flaggerv1.CanaryAlert{
|
||||
{
|
||||
Name: "slack-dev",
|
||||
Severity: "info",
|
||||
ProviderRef: flaggerv1.CrossNamespaceObjectReference{
|
||||
Name: "slack",
|
||||
Namespace: "default",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "slack-prod",
|
||||
Severity: "info",
|
||||
ProviderRef: flaggerv1.CrossNamespaceObjectReference{
|
||||
Name: "slack",
|
||||
},
|
||||
},
|
||||
}
|
||||
mocks := newDaemonSetFixture(canary)
|
||||
|
||||
secret := newDaemonSetTestAlertProviderSecret()
|
||||
secret.Data = map[string][]byte{
|
||||
"address": []byte(ts.URL),
|
||||
}
|
||||
_, err := mocks.kubeClient.CoreV1().Secrets("default").Update(secret)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
// init canary and send alerts
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/weaveworks/flagger/pkg/metrics/observers"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/weaveworks/flagger/pkg/metrics/observers"
|
||||
|
||||
"go.uber.org/zap"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
hpav2 "k8s.io/api/autoscaling/v2beta1"
|
||||
@@ -28,11 +29,6 @@ import (
|
||||
"github.com/weaveworks/flagger/pkg/router"
|
||||
)
|
||||
|
||||
var (
|
||||
alwaysReady = func() bool { return true }
|
||||
noResyncPeriodFunc = func() time.Duration { return 0 }
|
||||
)
|
||||
|
||||
type fixture struct {
|
||||
canary *flaggerv1.Canary
|
||||
kubeClient kubernetes.Interface
|
||||
@@ -44,30 +40,30 @@ type fixture struct {
|
||||
router router.Interface
|
||||
}
|
||||
|
||||
func newFixture(c *flaggerv1.Canary) fixture {
|
||||
func newDeploymentFixture(c *flaggerv1.Canary) fixture {
|
||||
if c == nil {
|
||||
c = newTestCanary()
|
||||
c = newDeploymentTestCanary()
|
||||
}
|
||||
|
||||
// init Flagger clientset and register objects
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(
|
||||
c,
|
||||
newTestMetricTemplate(),
|
||||
newTestAlertProvider(),
|
||||
newDeploymentTestMetricTemplate(),
|
||||
newDeploymentTestAlertProvider(),
|
||||
)
|
||||
|
||||
// init Kubernetes clientset and register objects
|
||||
kubeClient := fake.NewSimpleClientset(
|
||||
newTestDeployment(),
|
||||
newTestService(),
|
||||
newTestHPA(),
|
||||
newTestConfigMap(),
|
||||
newTestConfigMapEnv(),
|
||||
newTestConfigMapVol(),
|
||||
newTestSecret(),
|
||||
newTestSecretEnv(),
|
||||
newTestSecretVol(),
|
||||
newTestAlertProviderSecret(),
|
||||
newDeploymentTestDeployment(),
|
||||
newDeploymentTestService(),
|
||||
newDeploymentTestHPA(),
|
||||
newDeploymentTestConfigMap(),
|
||||
newDeploymentTestConfigMapEnv(),
|
||||
newDeploymentTestConfigMapVol(),
|
||||
newDeploymentTestSecret(),
|
||||
newDeploymentTestSecretEnv(),
|
||||
newDeploymentTestSecretVol(),
|
||||
newDeploymentTestAlertProviderSecret(),
|
||||
)
|
||||
|
||||
logger, _ := logger.NewLogger("debug")
|
||||
@@ -113,8 +109,8 @@ func newFixture(c *flaggerv1.Canary) fixture {
|
||||
}
|
||||
ctrl.flaggerSynced = alwaysReady
|
||||
ctrl.flaggerInformers.CanaryInformer.Informer().GetIndexer().Add(c)
|
||||
ctrl.flaggerInformers.MetricInformer.Informer().GetIndexer().Add(newTestMetricTemplate())
|
||||
ctrl.flaggerInformers.AlertInformer.Informer().GetIndexer().Add(newTestAlertProvider())
|
||||
ctrl.flaggerInformers.MetricInformer.Informer().GetIndexer().Add(newDeploymentTestMetricTemplate())
|
||||
ctrl.flaggerInformers.AlertInformer.Informer().GetIndexer().Add(newDeploymentTestAlertProvider())
|
||||
|
||||
meshRouter := rf.MeshRouter("istio")
|
||||
|
||||
@@ -130,7 +126,7 @@ func newFixture(c *flaggerv1.Canary) fixture {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestConfigMap() *corev1.ConfigMap {
|
||||
func newDeploymentTestConfigMap() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -143,7 +139,7 @@ func newTestConfigMap() *corev1.ConfigMap {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestConfigMapV2() *corev1.ConfigMap {
|
||||
func newDeploymentTestConfigMapV2() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -157,7 +153,7 @@ func newTestConfigMapV2() *corev1.ConfigMap {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestConfigMapEnv() *corev1.ConfigMap {
|
||||
func newDeploymentTestConfigMapEnv() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -170,7 +166,7 @@ func newTestConfigMapEnv() *corev1.ConfigMap {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestConfigMapVol() *corev1.ConfigMap {
|
||||
func newDeploymentTestConfigMapVol() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -183,7 +179,7 @@ func newTestConfigMapVol() *corev1.ConfigMap {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestSecret() *corev1.Secret {
|
||||
func newDeploymentTestSecret() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -199,7 +195,7 @@ func newTestSecret() *corev1.Secret {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestSecretV2() *corev1.Secret {
|
||||
func newDeploymentTestSecretV2() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -215,7 +211,7 @@ func newTestSecretV2() *corev1.Secret {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestSecretEnv() *corev1.Secret {
|
||||
func newDeploymentTestSecretEnv() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -229,7 +225,7 @@ func newTestSecretEnv() *corev1.Secret {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestSecretVol() *corev1.Secret {
|
||||
func newDeploymentTestSecretVol() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -243,7 +239,7 @@ func newTestSecretVol() *corev1.Secret {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestCanary() *flaggerv1.Canary {
|
||||
func newDeploymentTestCanary() *flaggerv1.Canary {
|
||||
cd := &flaggerv1.Canary{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -299,18 +295,13 @@ func newTestCanary() *flaggerv1.Canary {
|
||||
return cd
|
||||
}
|
||||
|
||||
func toFloatPtr(val int) *float64 {
|
||||
v := float64(val)
|
||||
return &v
|
||||
}
|
||||
|
||||
func newTestCanaryMirror() *flaggerv1.Canary {
|
||||
cd := newTestCanary()
|
||||
func newDeploymentTestCanaryMirror() *flaggerv1.Canary {
|
||||
cd := newDeploymentTestCanary()
|
||||
cd.Spec.CanaryAnalysis.Mirror = true
|
||||
return cd
|
||||
}
|
||||
|
||||
func newTestCanaryAB() *flaggerv1.Canary {
|
||||
func newDeploymentTestCanaryAB() *flaggerv1.Canary {
|
||||
cd := &flaggerv1.Canary{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -371,7 +362,7 @@ func newTestCanaryAB() *flaggerv1.Canary {
|
||||
return cd
|
||||
}
|
||||
|
||||
func newTestDeployment() *appsv1.Deployment {
|
||||
func newDeploymentTestDeployment() *appsv1.Deployment {
|
||||
d := &appsv1.Deployment{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -498,7 +489,7 @@ func newTestDeployment() *appsv1.Deployment {
|
||||
return d
|
||||
}
|
||||
|
||||
func newTestDeploymentV2() *appsv1.Deployment {
|
||||
func newDeploymentTestDeploymentV2() *appsv1.Deployment {
|
||||
d := &appsv1.Deployment{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -608,7 +599,7 @@ func newTestDeploymentV2() *appsv1.Deployment {
|
||||
return d
|
||||
}
|
||||
|
||||
func newTestService() *corev1.Service {
|
||||
func newDeploymentTestService() *corev1.Service {
|
||||
d := &corev1.Service{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -634,7 +625,7 @@ func newTestService() *corev1.Service {
|
||||
return d
|
||||
}
|
||||
|
||||
func newTestServiceV2() *corev1.Service {
|
||||
func newDeploymentTestServiceV2() *corev1.Service {
|
||||
d := &corev1.Service{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: appsv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -660,7 +651,7 @@ func newTestServiceV2() *corev1.Service {
|
||||
return d
|
||||
}
|
||||
|
||||
func newTestHPA() *hpav2.HorizontalPodAutoscaler {
|
||||
func newDeploymentTestHPA() *hpav2.HorizontalPodAutoscaler {
|
||||
h := &hpav2.HorizontalPodAutoscaler{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: hpav2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -688,7 +679,7 @@ func newTestHPA() *hpav2.HorizontalPodAutoscaler {
|
||||
return h
|
||||
}
|
||||
|
||||
func newTestMetricTemplate() *flaggerv1.MetricTemplate {
|
||||
func newDeploymentTestMetricTemplate() *flaggerv1.MetricTemplate {
|
||||
provider := flaggerv1.MetricTemplateProvider{
|
||||
Type: "prometheus",
|
||||
Address: "fake",
|
||||
@@ -711,7 +702,7 @@ func newTestMetricTemplate() *flaggerv1.MetricTemplate {
|
||||
return template
|
||||
}
|
||||
|
||||
func newTestAlertProviderSecret() *corev1.Secret {
|
||||
func newDeploymentTestAlertProviderSecret() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -725,7 +716,7 @@ func newTestAlertProviderSecret() *corev1.Secret {
|
||||
}
|
||||
}
|
||||
|
||||
func newTestAlertProvider() *flaggerv1.AlertProvider {
|
||||
func newDeploymentTestAlertProvider() *flaggerv1.AlertProvider {
|
||||
return &flaggerv1.AlertProvider{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: flaggerv1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
"github.com/weaveworks/flagger/pkg/notifier"
|
||||
)
|
||||
|
||||
func TestScheduler_Init(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentInit(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
_, err := mocks.kubeClient.AppsV1().Deployments("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
@@ -25,12 +25,12 @@ func TestScheduler_Init(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_NewRevision(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentNewRevision(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// update
|
||||
dep2 := newTestDeploymentV2()
|
||||
dep2 := newDeploymentTestDeploymentV2()
|
||||
_, err := mocks.kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
@@ -49,8 +49,8 @@ func TestScheduler_NewRevision(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_Rollback(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentRollback(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
@@ -103,8 +103,8 @@ func TestScheduler_Rollback(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_SkipAnalysis(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentSkipAnalysis(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
@@ -120,7 +120,7 @@ func TestScheduler_SkipAnalysis(t *testing.T) {
|
||||
}
|
||||
|
||||
// update
|
||||
dep2 := newTestDeploymentV2()
|
||||
dep2 := newDeploymentTestDeploymentV2()
|
||||
_, err = mocks.kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
@@ -144,13 +144,13 @@ func TestScheduler_SkipAnalysis(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_NewRevisionReset(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentNewRevisionReset(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// first update
|
||||
dep2 := newTestDeploymentV2()
|
||||
dep2 := newDeploymentTestDeploymentV2()
|
||||
_, err := mocks.kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
@@ -206,8 +206,8 @@ func TestScheduler_NewRevisionReset(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_Promotion(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentPromotion(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
@@ -223,7 +223,7 @@ func TestScheduler_Promotion(t *testing.T) {
|
||||
}
|
||||
|
||||
// update
|
||||
dep2 := newTestDeploymentV2()
|
||||
dep2 := newDeploymentTestDeploymentV2()
|
||||
_, err = mocks.kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
@@ -232,13 +232,13 @@ func TestScheduler_Promotion(t *testing.T) {
|
||||
// detect pod spec changes
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
config2 := newTestConfigMapV2()
|
||||
config2 := newDeploymentTestConfigMapV2()
|
||||
_, err = mocks.kubeClient.CoreV1().ConfigMaps("default").Update(config2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
secret2 := newTestSecretV2()
|
||||
secret2 := newDeploymentTestSecretV2()
|
||||
_, err = mocks.kubeClient.CoreV1().Secrets("default").Update(secret2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
@@ -357,13 +357,13 @@ func TestScheduler_Promotion(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_Mirroring(t *testing.T) {
|
||||
mocks := newFixture(newTestCanaryMirror())
|
||||
func TestScheduler_DeploymentMirroring(t *testing.T) {
|
||||
mocks := newDeploymentFixture(newDeploymentTestCanaryMirror())
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// update
|
||||
dep2 := newTestDeploymentV2()
|
||||
dep2 := newDeploymentTestDeploymentV2()
|
||||
_, err := mocks.kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
@@ -415,13 +415,13 @@ func TestScheduler_Mirroring(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_ABTesting(t *testing.T) {
|
||||
mocks := newFixture(newTestCanaryAB())
|
||||
func TestScheduler_DeploymentABTesting(t *testing.T) {
|
||||
mocks := newDeploymentFixture(newDeploymentTestCanaryAB())
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
|
||||
// update
|
||||
dep2 := newTestDeploymentV2()
|
||||
dep2 := newDeploymentTestDeploymentV2()
|
||||
_, err := mocks.kubeClient.AppsV1().Deployments("default").Update(dep2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
@@ -503,8 +503,8 @@ func TestScheduler_ABTesting(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_PortDiscovery(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentPortDiscovery(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
|
||||
// enable port discovery
|
||||
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
@@ -547,8 +547,8 @@ func TestScheduler_PortDiscovery(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_TargetPortNumber(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentTargetPortNumber(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
|
||||
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
@@ -592,8 +592,8 @@ func TestScheduler_TargetPortNumber(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_TargetPortName(t *testing.T) {
|
||||
mocks := newFixture(nil)
|
||||
func TestScheduler_DeploymentTargetPortName(t *testing.T) {
|
||||
mocks := newDeploymentFixture(nil)
|
||||
|
||||
cd, err := mocks.flaggerClient.FlaggerV1beta1().Canaries("default").Get("podinfo", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
@@ -637,7 +637,7 @@ func TestScheduler_TargetPortName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScheduler_Alerts(t *testing.T) {
|
||||
func TestScheduler_DeploymentAlerts(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
b, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
@@ -654,7 +654,7 @@ func TestScheduler_Alerts(t *testing.T) {
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
canary := newTestCanary()
|
||||
canary := newDeploymentTestCanary()
|
||||
canary.Spec.CanaryAnalysis.Alerts = []flaggerv1.CanaryAlert{
|
||||
{
|
||||
Name: "slack-dev",
|
||||
@@ -672,9 +672,9 @@ func TestScheduler_Alerts(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
mocks := newFixture(canary)
|
||||
mocks := newDeploymentFixture(canary)
|
||||
|
||||
secret := newTestAlertProviderSecret()
|
||||
secret := newDeploymentTestAlertProviderSecret()
|
||||
secret.Data = map[string][]byte{
|
||||
"address": []byte(ts.URL),
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
func TestScheduler_ServicePromotion(t *testing.T) {
|
||||
mocks := newFixture(newTestServiceCanary())
|
||||
mocks := newDeploymentFixture(newTestServiceCanary())
|
||||
|
||||
// init
|
||||
mocks.ctrl.advanceCanary("podinfo", "default", true)
|
||||
@@ -25,7 +25,7 @@ func TestScheduler_ServicePromotion(t *testing.T) {
|
||||
}
|
||||
|
||||
// update
|
||||
svc2 := newTestServiceV2()
|
||||
svc2 := newDeploymentTestServiceV2()
|
||||
_, err = mocks.kubeClient.CoreV1().Services("default").Update(svc2)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
|
||||
Reference in New Issue
Block a user