-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
e2e: adding testcases with recipe #1736
base: main
Are you sure you want to change the base?
Changes from 1 commit
6ab815a
59eb075
637e9a8
5d4f75c
d173ef8
0b89d36
ab2c18f
80465f7
be376f8
d912252
20a07d0
8d6e098
94f96c1
36c10d2
3bc86fa
c285a16
ac85abf
3bbc759
2975b36
f4677aa
078f770
8f8ada6
30dc1db
cb53056
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,17 +4,36 @@ | |
package deployers | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
|
||
"github.com/ramendr/ramen/e2e/types" | ||
"github.com/ramendr/ramen/e2e/util" | ||
recipe "github.com/ramendr/recipe/api/v1alpha1" | ||
"k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
k8stypes "k8s.io/apimachinery/pkg/types" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
type DiscoveredApp struct{} | ||
const timeout = 300 | ||
|
||
type DiscoveredApp struct { | ||
IncludeRecipe bool | ||
IncludeHooks bool | ||
} | ||
|
||
func (d DiscoveredApp) GetName() string { | ||
if d.IncludeRecipe { | ||
if d.IncludeHooks { | ||
return "disapp-recipe-hooks" | ||
} | ||
|
||
return "disapp-recipe" | ||
} | ||
|
||
return "disapp" | ||
} | ||
|
||
|
@@ -68,6 +87,16 @@ func (d DiscoveredApp) Deploy(ctx types.Context) error { | |
|
||
log.Info("Workload deployed") | ||
|
||
// recipe needs to be created based on flags | ||
if d.IncludeRecipe { | ||
recipeName := ctx.Name() + "-recipe" | ||
if err := createRecipe(recipeName, appNamespace, d.IncludeHooks); err != nil { | ||
log.Info("recipe creation failed") | ||
} | ||
|
||
log.Info("recipe created on both dr clusters") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
|
@@ -96,6 +125,22 @@ func (d DiscoveredApp) Undeploy(ctx types.Context) error { | |
return err | ||
} | ||
|
||
if d.IncludeRecipe { | ||
recipeName := ctx.Name() + "-recipe" | ||
|
||
log.Infof("Deleting recipe on cluster %q", drpolicy.Spec.DRClusters[0]) | ||
|
||
if err := deleteRecipe(util.Ctx.C1.Client, recipeName, appNamespace); err != nil { | ||
return err | ||
} | ||
|
||
log.Infof("Deleting recipe on cluster %q", drpolicy.Spec.DRClusters[1]) | ||
|
||
if err := deleteRecipe(util.Ctx.C2.Client, recipeName, appNamespace); err != nil { | ||
return err | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same, part of the workload. |
||
|
||
log.Infof("Deleting namespace %q on cluster %q", appNamespace, drpolicy.Spec.DRClusters[0]) | ||
|
||
// delete namespace on both clusters | ||
|
@@ -117,3 +162,181 @@ func (d DiscoveredApp) Undeploy(ctx types.Context) error { | |
func (d DiscoveredApp) IsDiscovered() bool { | ||
return true | ||
} | ||
|
||
func createRecipe(name, namespace string, includeHooks bool) error { | ||
var recipe *recipe.Recipe | ||
if includeHooks { | ||
recipe = getRecipeWithHooks(name, namespace) | ||
} else { | ||
recipe = getRecipeWithoutHooks(name, namespace) | ||
} | ||
|
||
err := util.Ctx.C1.Client.Create(context.Background(), recipe) | ||
if err != nil { | ||
if !errors.IsAlreadyExists(err) { | ||
return err | ||
} | ||
|
||
util.Ctx.Log.Info("recipe " + name + " already exists" + " in the cluster " + "C1") | ||
} | ||
|
||
err = util.Ctx.C2.Client.Create(context.Background(), recipe) | ||
if err != nil { | ||
if !errors.IsAlreadyExists(err) { | ||
return err | ||
} | ||
|
||
util.Ctx.Log.Info("recipe " + name + " already exists" + " in the cluster " + "C2") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. functions for creating recipes should move to recipes package or maybe workloads since recipes are part of a workload. |
||
func getRecipeWithoutHooks(name, namespace string) *recipe.Recipe { | ||
return &recipe.Recipe{ | ||
TypeMeta: metav1.TypeMeta{ | ||
Kind: "Recipe", | ||
APIVersion: "ramendr.openshift.io/v1alpha1", | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: namespace, | ||
}, | ||
Spec: recipe.RecipeSpec{ | ||
AppType: "busybox", | ||
Groups: []*recipe.Group{ | ||
{ | ||
Name: "rg1", | ||
Type: "resource", | ||
BackupRef: "rg1", | ||
IncludedNamespaces: []string{ | ||
namespace, | ||
}, | ||
LabelSelector: &metav1.LabelSelector{ | ||
MatchExpressions: []metav1.LabelSelectorRequirement{ | ||
{ | ||
Key: "appname", | ||
Operator: metav1.LabelSelectorOpIn, | ||
Values: []string{"busybox"}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
Workflows: []*recipe.Workflow{ | ||
{ | ||
Name: "backup", | ||
Sequence: []map[string]string{ | ||
{ | ||
"group": "rg1", | ||
}, | ||
}, | ||
}, | ||
{ | ||
Name: "restore", | ||
Sequence: []map[string]string{ | ||
{ | ||
"group": "rg1", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func getRecipeWithHooks(name, namespace string) *recipe.Recipe { | ||
return &recipe.Recipe{ | ||
TypeMeta: metav1.TypeMeta{ | ||
Kind: "Recipe", | ||
APIVersion: "ramendr.openshift.io/v1alpha1", | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: namespace, | ||
}, | ||
Spec: recipe.RecipeSpec{ | ||
AppType: "busybox", | ||
Groups: []*recipe.Group{ | ||
{ | ||
Name: "rg1", | ||
Type: "resource", | ||
BackupRef: "rg1", | ||
IncludedNamespaces: []string{ | ||
namespace, | ||
}, | ||
LabelSelector: &metav1.LabelSelector{ | ||
MatchExpressions: []metav1.LabelSelectorRequirement{ | ||
{ | ||
Key: "appname", | ||
Operator: metav1.LabelSelectorOpIn, | ||
Values: []string{"busybox"}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
Hooks: []*recipe.Hook{ | ||
getHookSpec(namespace, "backup"), | ||
getHookSpec(namespace, "restore"), | ||
}, | ||
Workflows: []*recipe.Workflow{ | ||
{ | ||
Name: "backup", | ||
Sequence: []map[string]string{ | ||
{ | ||
"hook": "backup/check-replicas", | ||
}, | ||
{ | ||
"group": "rg1", | ||
}, | ||
}, | ||
}, | ||
{ | ||
Name: "restore", | ||
Sequence: []map[string]string{ | ||
{ | ||
"group": "rg1", | ||
}, | ||
{ | ||
"hook": "restore/check-replicas", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func getHookSpec(namespace, hookType string) *recipe.Hook { | ||
return &recipe.Hook{ | ||
Name: hookType, | ||
Type: "check", | ||
Namespace: namespace, | ||
NameSelector: "busybox", | ||
SelectResource: "deployment", | ||
Timeout: timeout, | ||
Chks: []*recipe.Check{ | ||
{ | ||
Name: "check-replicas", | ||
Condition: "{$.spec.replicas} == {$.status.readyReplicas}", | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func deleteRecipe(client client.Client, name, namespace string) error { | ||
r := &recipe.Recipe{} | ||
key := k8stypes.NamespacedName{Namespace: namespace, Name: name} | ||
|
||
err := client.Get(context.Background(), key, r) | ||
if err != nil { | ||
if !errors.IsNotFound(err) { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
return client.Delete(context.Background(), r) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,11 +25,16 @@ const ( | |
) | ||
|
||
var ( | ||
Workloads = []types.Workload{} | ||
subscription = &deployers.Subscription{} | ||
appset = &deployers.ApplicationSet{} | ||
discoveredApps = &deployers.DiscoveredApp{} | ||
Deployers = []types.Deployer{subscription, appset, discoveredApps} | ||
Workloads = []types.Workload{} | ||
subscription = &deployers.Subscription{} | ||
appset = &deployers.ApplicationSet{} | ||
discoveredApps = &deployers.DiscoveredApp{} | ||
discoveredAppsWithoutHook = &deployers.DiscoveredApp{IncludeRecipe: true, IncludeHooks: false} | ||
discoveredAppsWithHook = &deployers.DiscoveredApp{IncludeRecipe: true, IncludeHooks: true} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we need to keep discoveredApps deployer and add workloads including a recipe with/without hooks. Also we don't want to add so many tests - this add 2 new deployers, which adds 4 new tests. Why do w need to test recipe without hook and recipe with hook with both rbd and ceph storage? Does recipe/hooks care about the storage which is handled by ramen anyway? |
||
Deployers = []types.Deployer{ | ||
subscription, appset, discoveredApps, discoveredAppsWithoutHook, | ||
discoveredAppsWithHook, | ||
} | ||
) | ||
|
||
func generateWorkloads([]types.Workload) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be part of the workload, not of the deployer.