Skip to content
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

feat: add reloader scenario tests #1668

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions apptests/appscenarios/appscenarios.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Package appscenarios provides a set of application test scenarios that can be executed
// in a Kubernetes environment. The package defines an AppScenario interface that specifies the
// behavior and name of each scenario, and a List type that implements methods to execute, get,
// and check scenarios.
//
// The package currently supports one scenario for the reloader application, but more scenarios can be
// added by implementing the AppScenario interface and registering them in the scenariosList variable.
package appscenarios

import (
"context"
"fmt"
"os"
"path/filepath"

"github.com/mesosphere/kommander-applications/apptests/environment"
)

// AppScenario defines the behavior and name of an application test scenario
type AppScenario interface {
Execute(context.Context, *environment.Env) error // logic implemented by a scenario
Name() string // scenario name
}

type List map[string]AppScenario

// Execute runs all the scenarios in the list and returns the first error encountered, if any.
func (s List) Execute(ctx context.Context, env *environment.Env) error {
for _, sc := range s {
if err := sc.Execute(ctx, env); err != nil {
return err
}
}
return nil
}

// Get returns the associated scenario for the given application name, or nil if it does not exist.
func Get(application string) AppScenario {
s, ok := scenariosList[application]
if !ok {
return nil
}
return s
}

// Has checks if the associated scenario for the given application exist.
func Has(application string) bool {
_, ok := scenariosList[application]
return ok
}

// absolutePathTo returns the absolute path to the given application directory.
func absolutePathTo(application string) (string, error) {
wd, err := os.Getwd()
if err != nil {
return "", err
}

// determining the execution path.
var base string
_, err = os.Stat(filepath.Join(wd, "services"))
if os.IsNotExist(err) {
base = "../.."
} else {
base = ""
}

dir, err := filepath.Abs(filepath.Join(wd, base, "services", application))
if err != nil {
return "", err
}

// filepath.Glob returns a sorted slice of matching paths
matches, err := filepath.Glob(filepath.Join(dir, "*"))
if err != nil {
return "", err
}

if len(matches) == 0 {
return "", fmt.Errorf(
"no application directory found for %s in the given path:%s",
application, dir)
}

return matches[0], nil

}

// This is the ScenarioList of all available scenarios.
var scenariosList = List{
"reloader": reloader{},
}
17 changes: 17 additions & 0 deletions apptests/appscenarios/appscenarios_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package appscenarios

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

func TestAbsolutePathTo(t *testing.T) {
absAppPath, err := absolutePathTo("reloader")
assert.NoError(t, err)

expected := filepath.Join("kommander-applications", "services", "reloader")
assert.Contains(t, absAppPath, expected)
assert.NotEmpty(t, filepath.Base(absAppPath))
}
84 changes: 84 additions & 0 deletions apptests/appscenarios/reloader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package appscenarios

import (
"context"
"path/filepath"
"time"

fluxhelmv2beta1 "github.com/fluxcd/helm-controller/api/v2beta1"
"github.com/mesosphere/kommander-applications/apptests/environment"
"github.com/mesosphere/kommander-applications/apptests/flux"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
genericCLient "sigs.k8s.io/controller-runtime/pkg/client"
)

type reloader struct{}

func (r reloader) Name() string {
return "reloader"
}

var _ AppScenario = (*reloader)(nil)

const (
pollInterval = 2 * time.Second
kommanderNamespace = "kommander"
kommanderFluxNamespace = "kommander-flux"
)

func (r reloader) Execute(ctx context.Context, env *environment.Env) error {
appPath, err := absolutePathTo(r.Name())
if err != nil {
return err
}

// apply defaults config maps first
defaultKustomizations := filepath.Join(appPath, "/defaults")
err = env.ApplyKustomizations(ctx, defaultKustomizations, map[string]string{
"releaseNamespace": kommanderNamespace,
})
if err != nil {
return err
}
// apply the rest of kustomizations
err = env.ApplyKustomizations(ctx, appPath, map[string]string{
"releaseNamespace": kommanderNamespace,
})
if err != nil {
return err
}

client, err := genericCLient.New(env.K8sClient.Config(), genericCLient.Options{Scheme: flux.NewScheme()})
if err != nil {
return err
}

hr := &fluxhelmv2beta1.HelmRelease{
TypeMeta: metav1.TypeMeta{
Kind: fluxhelmv2beta1.HelmReleaseKind,
APIVersion: fluxhelmv2beta1.GroupVersion.Version,
},
ObjectMeta: metav1.ObjectMeta{
Name: r.Name(),
Namespace: kommanderNamespace,
},
}

err = wait.PollUntilContextCancel(ctx, pollInterval, true, func(ctx context.Context) (done bool, err error) {
err = client.Get(ctx, genericCLient.ObjectKeyFromObject(hr), hr)
if err != nil {
return false, err
}

for _, cond := range hr.Status.Conditions {
if cond.Status == metav1.ConditionTrue &&
cond.Type == fluxhelmv2beta1.ReleasedCondition {
return true, nil
}
}
return false, nil
})

return err
}
22 changes: 22 additions & 0 deletions apptests/appscenarios/reloader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package appscenarios

import (
"context"
"testing"

"github.com/mesosphere/kommander-applications/apptests/environment"
"github.com/stretchr/testify/assert"
)

func TestListExecute(t *testing.T) {
env := &environment.Env{}
ctx := context.Background()

err := env.Provision(ctx)
assert.NoError(t, err)
defer env.Destroy(ctx)

r := reloader{}
err = r.Execute(ctx, env)
assert.NoError(t, err)
}
23 changes: 19 additions & 4 deletions apptests/environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"time"

Expand Down Expand Up @@ -49,7 +50,7 @@ type Env struct {
func (e *Env) Provision(ctx context.Context) error {
var err error

kustomizePath, err := AbsolutePathToBase()
kustomizePath, err := absolutePathToBase()
if err != nil {
return err
}
Expand Down Expand Up @@ -217,7 +218,21 @@ func (e *Env) ApplyKustomizations(ctx context.Context, path string, substitution
return nil
}

// AbsolutePathToBase returns the absolute path to common/base directory.
func AbsolutePathToBase() (string, error) {
return filepath.Abs("../../common/base")
// absolutePathToBase returns the absolute path to common/base directory from the given working directory.
func absolutePathToBase() (string, error) {
wd, err := os.Getwd()
if err != nil {
return "", err
}

// determining the execution path.
var base string
_, err = os.Stat(filepath.Join(wd, "common", "base"))
if os.IsNotExist(err) {
base = "../.."
} else {
base = ""
}

return filepath.Join(wd, base, "common", "base"), nil
}
6 changes: 6 additions & 0 deletions apptests/environment/environment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ func TestProvision(t *testing.T) {
}

}

func TestAbsolutePathToBase(t *testing.T) {
s, err := absolutePathToBase()
assert.NoError(t, err)
assert.Contains(t, s, "kommander-applications/common/base")
}
Loading