-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add infrastructure stack run poller (#170)
* infrastructure stack poller * infrastructure stack poller * change names * register stack Reconciler * bump go cient * handle job * reconcile Job * create job * merge job spec * remove job check * add label selector * add label selector * update job reconciler * use new client to simplify job generation * default job spec * do not update run status * add run job generation * update variable name * add stack run job controller * check job status * move job logic * make defaultJobContainer private * update logs * update default job * fetch job pods * use pointer * update log * change error handling * add label selector * default image and version * add label selector * fix client * refactor * refactor * fetch job pod status * update exit codes * start adding tests for stack run job controller * fix tests * add more tests * fix job creation * add container envs * rebase * add job controller * fix unit tests * fix unmarshal job spec * sync step status * update step statuses * update mocks * ignore stack run * add default container annotation * initialize agent tests * add tests for stack agent * fix approval logic * add nil checks * add more tests * add tests to cover job creation * add missing mapping for sa * fix annotations mapping * cover job spec mapping * cover raw job spec mapping * add pipeline gate controller tests * fix make test * simplify test suite * cleanup other suites * simplify test suite * fix kustomize files * add image names * add image versions * change image * bump console client * fix linter --------- Co-authored-by: Marcin Maciaszczyk <[email protected]> Co-authored-by: michaeljguarino <[email protected]>
- Loading branch information
1 parent
d765f7b
commit 9d3fb48
Showing
25 changed files
with
1,780 additions
and
105 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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package controller | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/go-logr/logr" | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
console "github.com/pluralsh/console-client-go" | ||
"github.com/pluralsh/deployment-operator/api/v1alpha1" | ||
"github.com/pluralsh/deployment-operator/pkg/client" | ||
"github.com/pluralsh/deployment-operator/pkg/test/common" | ||
"github.com/pluralsh/deployment-operator/pkg/test/mocks" | ||
"github.com/samber/lo" | ||
"github.com/stretchr/testify/mock" | ||
batchv1 "k8s.io/api/batch/v1" | ||
corev1 "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
"sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
) | ||
|
||
var _ = Describe("PipelineGate Controller", Ordered, func() { | ||
Context("When reconciling a resource", func() { | ||
const ( | ||
gateName = "gate-test" | ||
namespace = "default" | ||
id = "123" | ||
raw = `{"backoffLimit":4,"template":{"metadata":{"namespace":"default","creationTimestamp":null},"spec":{"containers":[{"name":"pi","image":"perl:5.34.0","command":["perl","-Mbignum=bpi","-wle","print bpi(2000)"],"resources":{}}],"restartPolicy":"Never"}}}` | ||
) | ||
|
||
gateCache := client.NewCache[console.PipelineGateFragment](time.Second, func(id string) (*console.PipelineGateFragment, error) { | ||
return &console.PipelineGateFragment{ | ||
ID: id, | ||
Name: "test", | ||
Spec: &console.GateSpecFragment{ | ||
Job: &console.JobSpecFragment{ | ||
Namespace: namespace, | ||
Raw: lo.ToPtr(raw), | ||
}, | ||
}, | ||
Status: nil, | ||
}, nil | ||
}) | ||
|
||
ctx := context.Background() | ||
gateNamespacedName := types.NamespacedName{Name: gateName, Namespace: namespace} | ||
pipelineGate := &v1alpha1.PipelineGate{} | ||
|
||
BeforeAll(func() { | ||
By("Creating pipeline gate") | ||
err := kClient.Get(ctx, gateNamespacedName, pipelineGate) | ||
if err != nil && errors.IsNotFound(err) { | ||
resource := &v1alpha1.PipelineGate{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: gateName, | ||
Namespace: namespace, | ||
}, | ||
Spec: v1alpha1.PipelineGateSpec{ | ||
ID: id, | ||
Name: "test", | ||
Type: v1alpha1.GateType(console.GateTypeJob), | ||
GateSpec: &v1alpha1.GateSpec{ | ||
JobSpec: &batchv1.JobSpec{ | ||
Template: corev1.PodTemplateSpec{ | ||
ObjectMeta: metav1.ObjectMeta{}, | ||
Spec: corev1.PodSpec{ | ||
Containers: []corev1.Container{ | ||
{ | ||
Name: "image1", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
Expect(kClient.Create(ctx, resource)).To(Succeed()) | ||
} | ||
|
||
}) | ||
|
||
It("should set state pending", func() { | ||
fakeConsoleClient := mocks.NewClientMock(mocks.TestingT) | ||
fakeConsoleClient.On("UpdateGate", mock.Anything, mock.Anything).Return(nil) | ||
reconciler := &PipelineGateReconciler{ | ||
Client: kClient, | ||
ConsoleClient: fakeConsoleClient, | ||
GateCache: gateCache, | ||
Scheme: kClient.Scheme(), | ||
Log: logr.Logger{}, | ||
} | ||
_, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: gateNamespacedName}) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
existingGate := &v1alpha1.PipelineGate{} | ||
Expect(kClient.Get(ctx, gateNamespacedName, existingGate)).NotTo(HaveOccurred()) | ||
Expect(*existingGate.Status.State).Should(Equal(v1alpha1.GateState(console.GateStatePending))) | ||
|
||
}) | ||
|
||
It("should reconcile Pending Gate", func() { | ||
fakeConsoleClient := mocks.NewClientMock(mocks.TestingT) | ||
fakeConsoleClient.On("UpdateGate", mock.Anything, mock.Anything).Return(nil) | ||
reconciler := &PipelineGateReconciler{ | ||
Client: kClient, | ||
ConsoleClient: fakeConsoleClient, | ||
GateCache: gateCache, | ||
Scheme: kClient.Scheme(), | ||
Log: logr.Logger{}, | ||
} | ||
_, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: gateNamespacedName}) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
existingGate := &v1alpha1.PipelineGate{} | ||
Expect(kClient.Get(ctx, gateNamespacedName, existingGate)).NotTo(HaveOccurred()) | ||
Expect(*existingGate.Status.State).Should(Equal(v1alpha1.GateState(console.GateStateRunning))) | ||
existingJob := &batchv1.Job{} | ||
Expect(kClient.Get(ctx, gateNamespacedName, existingJob)).NotTo(HaveOccurred()) | ||
}) | ||
|
||
It("should open Gate", func() { | ||
fakeConsoleClient := mocks.NewClientMock(mocks.TestingT) | ||
fakeConsoleClient.On("UpdateGate", mock.Anything, mock.Anything).Return(nil) | ||
reconciler := &PipelineGateReconciler{ | ||
Client: kClient, | ||
ConsoleClient: fakeConsoleClient, | ||
GateCache: gateCache, | ||
Scheme: kClient.Scheme(), | ||
Log: logr.Logger{}, | ||
} | ||
|
||
existingJob := &batchv1.Job{} | ||
Expect(kClient.Get(ctx, gateNamespacedName, existingJob)).NotTo(HaveOccurred()) | ||
|
||
Expect(common.MaybePatch(kClient, existingJob, | ||
func(p *batchv1.Job) { | ||
p.Status.Conditions = []batchv1.JobCondition{ | ||
{ | ||
Type: batchv1.JobComplete, | ||
Status: corev1.ConditionTrue, | ||
}, | ||
} | ||
})).To(Succeed()) | ||
|
||
_, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: gateNamespacedName}) | ||
Expect(err).NotTo(HaveOccurred()) | ||
|
||
existingGate := &v1alpha1.PipelineGate{} | ||
Expect(kClient.Get(ctx, gateNamespacedName, existingGate)).NotTo(HaveOccurred()) | ||
Expect(*existingGate.Status.State).Should(Equal(v1alpha1.GateState(console.GateStateOpen))) | ||
|
||
Expect(kClient.Delete(ctx, existingGate)).To(Succeed()) | ||
Expect(kClient.Delete(ctx, existingJob)).To(Succeed()) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.