Merge pull request #1696 from allenporter/flux-cmd-create
Add tests for create source git
This commit is contained in:
131
cmd/flux/create_source_git_test.go
Normal file
131
cmd/flux/create_source_git_test.go
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
// +build unit
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/fluxcd/pkg/apis/meta"
|
||||||
|
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pollInterval = 50 * time.Millisecond
|
||||||
|
var testTimeout = 10 * time.Second
|
||||||
|
|
||||||
|
// Update the GitRepository once created to exercise test specific behavior
|
||||||
|
type reconcileFunc func(repo *sourcev1.GitRepository)
|
||||||
|
|
||||||
|
// reconciler waits for an object to be created, then invokes a test supplied
|
||||||
|
// function to mutate that object, simulating a controller.
|
||||||
|
// Test should invoke run() to run the background reconciler task which
|
||||||
|
// polls to wait for the object to exist before applying the update function.
|
||||||
|
// Any errors from the reconciler are asserted on test completion.
|
||||||
|
type reconciler struct {
|
||||||
|
client client.Client
|
||||||
|
name types.NamespacedName
|
||||||
|
reconcile reconcileFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the background task that waits for the object to exist then applies
|
||||||
|
// the update function.
|
||||||
|
func (r *reconciler) run(t *testing.T) {
|
||||||
|
result := make(chan error)
|
||||||
|
go func() {
|
||||||
|
defer close(result)
|
||||||
|
err := wait.PollImmediate(
|
||||||
|
pollInterval,
|
||||||
|
testTimeout,
|
||||||
|
r.conditionFunc)
|
||||||
|
result <- err
|
||||||
|
}()
|
||||||
|
t.Cleanup(func() {
|
||||||
|
if err := <-result; err != nil {
|
||||||
|
t.Errorf("Failure from test reconciler: '%v':", err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// A ConditionFunction that waits for the named GitRepository to be created,
|
||||||
|
// then sets the ready condition to true.
|
||||||
|
func (r *reconciler) conditionFunc() (bool, error) {
|
||||||
|
var repo sourcev1.GitRepository
|
||||||
|
if err := r.client.Get(context.Background(), r.name, &repo); err != nil {
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
return false, nil // Keep polling until object is created
|
||||||
|
}
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
r.reconcile(&repo)
|
||||||
|
err := r.client.Status().Update(context.Background(), &repo)
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateSourceGit(t *testing.T) {
|
||||||
|
// Default command used for multiple tests
|
||||||
|
var command = "create source git podinfo --url=https://github.com/stefanprodan/podinfo --branch=master --timeout=" + testTimeout.String()
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
args string
|
||||||
|
assert assertFunc
|
||||||
|
reconcile reconcileFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"NoArgs",
|
||||||
|
"create source git",
|
||||||
|
assertError("GitRepository source name is required"),
|
||||||
|
nil,
|
||||||
|
}, {
|
||||||
|
"Succeeded",
|
||||||
|
command,
|
||||||
|
assertGoldenFile("testdata/create_source_git/success.golden"),
|
||||||
|
func(repo *sourcev1.GitRepository) {
|
||||||
|
meta.SetResourceCondition(repo, meta.ReadyCondition, metav1.ConditionTrue, sourcev1.GitOperationSucceedReason, "succeeded message")
|
||||||
|
repo.Status.Artifact = &sourcev1.Artifact{
|
||||||
|
Path: "some-path",
|
||||||
|
Revision: "v1",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
"Failed",
|
||||||
|
command,
|
||||||
|
assertError("failed message"),
|
||||||
|
func(repo *sourcev1.GitRepository) {
|
||||||
|
meta.SetResourceCondition(repo, meta.ReadyCondition, metav1.ConditionFalse, sourcev1.URLInvalidReason, "failed message")
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
"NoArtifact",
|
||||||
|
command,
|
||||||
|
assertError("GitRepository source reconciliation completed but no artifact was found"),
|
||||||
|
func(repo *sourcev1.GitRepository) {
|
||||||
|
// Updated with no artifact
|
||||||
|
meta.SetResourceCondition(repo, meta.ReadyCondition, metav1.ConditionTrue, sourcev1.GitOperationSucceedReason, "succeeded message")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
ns := allocateNamespace("podinfo")
|
||||||
|
setupTestNamespace(ns, t)
|
||||||
|
if tc.reconcile != nil {
|
||||||
|
r := reconciler{
|
||||||
|
client: testEnv.client,
|
||||||
|
name: types.NamespacedName{Namespace: ns, Name: "podinfo"},
|
||||||
|
reconcile: tc.reconcile,
|
||||||
|
}
|
||||||
|
r.run(t)
|
||||||
|
}
|
||||||
|
cmd := cmdTestCase{
|
||||||
|
args: tc.args + " -n=" + ns,
|
||||||
|
assert: tc.assert,
|
||||||
|
}
|
||||||
|
cmd.runTestCmd(t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/fluxcd/flux2/internal/utils"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/mattn/go-shellwords"
|
"github.com/mattn/go-shellwords"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
@@ -132,7 +133,9 @@ func NewTestEnvKubeManager(testClusterMode TestClusterMode) (*testEnvKubeManager
|
|||||||
|
|
||||||
tmpFilename := filepath.Join("/tmp", "kubeconfig-"+time.Nanosecond.String())
|
tmpFilename := filepath.Join("/tmp", "kubeconfig-"+time.Nanosecond.String())
|
||||||
os.WriteFile(tmpFilename, kubeConfig, 0644)
|
os.WriteFile(tmpFilename, kubeConfig, 0644)
|
||||||
k8sClient, err := client.NewWithWatch(cfg, client.Options{})
|
k8sClient, err := client.NewWithWatch(cfg, client.Options{
|
||||||
|
Scheme: utils.NewScheme(),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -158,7 +161,9 @@ func NewTestEnvKubeManager(testClusterMode TestClusterMode) (*testEnvKubeManager
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
k8sClient, err := client.NewWithWatch(cfg, client.Options{})
|
k8sClient, err := client.NewWithWatch(cfg, client.Options{
|
||||||
|
Scheme: utils.NewScheme(),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -32,3 +35,14 @@ func TestMain(m *testing.M) {
|
|||||||
|
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupTestNamespace(namespace string, t *testing.T) {
|
||||||
|
ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
|
||||||
|
err := testEnv.client.Create(context.Background(), ns)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create namespace: %v", err)
|
||||||
|
}
|
||||||
|
t.Cleanup(func() {
|
||||||
|
_ = testEnv.client.Delete(context.Background(), ns)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
6
cmd/flux/testdata/create_source_git/success.golden
vendored
Normal file
6
cmd/flux/testdata/create_source_git/success.golden
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
✚ generating GitRepository source
|
||||||
|
► applying GitRepository source
|
||||||
|
✔ GitRepository source created
|
||||||
|
◎ waiting for GitRepository source reconciliation
|
||||||
|
✔ GitRepository source reconciliation completed
|
||||||
|
✔ fetched revision: v1
|
||||||
Reference in New Issue
Block a user