Skip to content

Commit

Permalink
fix: test of InitializePeriodics implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
msvticket committed Aug 9, 2023
1 parent bfc42f8 commit 549606f
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 13 deletions.
36 changes: 23 additions & 13 deletions pkg/plugins/trigger/periodic.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (

type PeriodicAgent struct {
Namespace string
SCMClient *scm.Client
}

const fieldManager = "lighthouse"
Expand Down Expand Up @@ -154,6 +155,15 @@ func (pa *PeriodicAgent) PeriodicsInitialized(namespace string, kc kubeclient.In

func (pa *PeriodicAgent) InitializePeriodics(kc kubeclient.Interface, configAgent *config.Agent, fileBrowsers *filebrowser.FileBrowsers) {
// TODO: Add lock so 2 InitializePeriodics can't run at the same time
if pa.SCMClient == nil {
_, scmClient, _, _, err := util.GetSCMClient("", configAgent.Config)
if err != nil {
logrus.Errorf("failed to create SCM scmClient: %s", err.Error())
return
}
pa.SCMClient = scmClient
}

resolverCache := inrepo.NewResolverCache()
fc := filebrowser.NewFetchCache()
c := configAgent.Config()
Expand All @@ -172,7 +182,7 @@ func (pa *PeriodicAgent) InitializePeriodics(kc kubeclient.Interface, configAgen
cronMap[cronjob.Labels["repo"]][cronjob.Labels["trigger"]] = &cronjob
}

for fullName := range filterPeriodics(c.InRepoConfig.Enabled, configAgent) {
for fullName := range pa.filterPeriodics(c.InRepoConfig.Enabled, configAgent) {
repoCronJobs, repoCronExists := cronMap[fullName]
repoCM, repoCmExists := cmMap[fullName]
org, repo := scm.Split(fullName)
Expand Down Expand Up @@ -280,7 +290,7 @@ func (pa *PeriodicAgent) UpdatePeriodicsForRepo(
}
}

resourceName := fmt.Sprintf("lighthouse-%s-%s", fullName, p.Name)
resourceName := fmt.Sprintf("lighthouse-%s-%s-%s", org, repo, p.Name)

err := p.LoadPipeline(l)
if err != nil {
Expand Down Expand Up @@ -309,10 +319,14 @@ func (pa *PeriodicAgent) UpdatePeriodicsForRepo(
} else {
cm = (&applyv1.ConfigMapApplyConfiguration{}).WithName(resourceName).WithLabels(labels)
}
if cm.Data == nil {
cm.Data = make(map[string]string)
}
cm.Data["lighthousejob.yaml"] = string(lighthouseData)

_, err := cmInterface.Apply(context.TODO(), cm, metav1.ApplyOptions{Force: true, FieldManager: fieldManager})
if err != nil {
l.WithError(err).Errorf("failed to apply configmap")
return false
}
}
Expand All @@ -326,11 +340,12 @@ func (pa *PeriodicAgent) UpdatePeriodicsForRepo(
return true
}
} else {
cj = pa.constructCronJob(resourceName, *cj.Name, labels)
cj = pa.constructCronJob(resourceName, resourceName, labels)
}
cj.Spec.Schedule = &p.Cron
_, err := cjInterface.Apply(context.TODO(), cj, metav1.ApplyOptions{Force: true, FieldManager: fieldManager})
if err != nil {
l.WithError(err).Errorf("failed to apply cronjob")
return false
}
}
Expand Down Expand Up @@ -398,26 +413,21 @@ kubectl patch LighthouseJob $HOSTNAME --type=merge --subresource status --patch
WithName(configMapName))))))))
}

func filterPeriodics(enabled map[string]*bool, agent *config.Agent) map[string]*bool {
_, scmClient, _, _, err := util.GetSCMClient("", agent.Config)
if err != nil {
logrus.Errorf("failed to create SCM scmClient: %s", err.Error())
return enabled
}
if scmClient.Contents == nil {
func (pa *PeriodicAgent) filterPeriodics(enabled map[string]*bool, agent *config.Agent) map[string]*bool {
if pa.SCMClient.Contents == nil {
return enabled
}

enable := true
hasPeriodics := make(map[string]*bool)
for fullName := range enabled {
list, _, err := scmClient.Contents.List(context.TODO(), fullName, ".lighthouse", "HEAD")
list, _, err := pa.SCMClient.Contents.List(context.TODO(), fullName, ".lighthouse", "HEAD")
if err != nil {
continue
}
for _, file := range list {
if file.Type == "dir" {
triggers, _, err := scmClient.Contents.Find(context.TODO(), fullName, file.Path+"/triggers.yaml", "HEAD")
triggers, _, err := pa.SCMClient.Contents.Find(context.TODO(), fullName, file.Path+"/triggers.yaml", "HEAD")
if err != nil {
continue
}
Expand All @@ -426,7 +436,7 @@ func filterPeriodics(enabled map[string]*bool, agent *config.Agent) map[string]*
}
}
}
delayForRate(scmClient.Rate())
delayForRate(pa.SCMClient.Rate())
}

return hasPeriodics
Expand Down
120 changes: 120 additions & 0 deletions pkg/plugins/trigger/periodic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package trigger

import (
"context"
"testing"

scmfake "github.com/jenkins-x/go-scm/scm/driver/fake"
"github.com/jenkins-x/lighthouse/pkg/config"
"github.com/jenkins-x/lighthouse/pkg/config/lighthouse"
"github.com/jenkins-x/lighthouse/pkg/filebrowser"
fbfake "github.com/jenkins-x/lighthouse/pkg/filebrowser/fake"
"github.com/stretchr/testify/require"
batchv1 "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
kubefake "k8s.io/client-go/kubernetes/fake"
clienttesting "k8s.io/client-go/testing"
)

var kubeClient *kubefake.Clientset

// TODO: verify creation of configmap and cronjob from trigger

func TestInitializePeriodics(t *testing.T) {
const namespace = "default"
newDefault, data := scmfake.NewDefault()
data.ContentDir = "test_data"

p := &PeriodicAgent{Namespace: namespace, SCMClient: newDefault}
kubeClient = kubefake.NewSimpleClientset(&v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{Name: "config"},
})

kubeClient.PrependReactor(
"patch",
"configmaps",
fakeUpsert,
)

kubeClient.PrependReactor(
"patch",
"cronjobs",
fakeUpsert,
)

var enabled = true
configAgent := &config.Agent{}
configAgent.Set(&config.Config{
ProwConfig: lighthouse.Config{
InRepoConfig: lighthouse.InRepoConfig{
Enabled: map[string]*bool{"testorg/myapp": &enabled},
},
},
})
fileBrowsers, err := filebrowser.NewFileBrowsers(filebrowser.GitHubURL, fbfake.NewFakeFileBrowser("test_data", true))
require.NoError(t, err, "failed to create filebrowsers")

p.InitializePeriodics(kubeClient, configAgent, fileBrowsers)

selector := "app=lighthouse-webhooks,component=periodic,repo,trigger"
cms, err := kubeClient.CoreV1().ConfigMaps(namespace).
List(context.TODO(), metav1.ListOptions{LabelSelector: selector})
require.NoError(t, err, "failed to get ConfigMaps")
require.Len(t, cms.Items, 1)
require.Equal(t, lighthouseJob, cms.Items[0].Data["lighthousejob.yaml"])

cjs, err := kubeClient.BatchV1().CronJobs(namespace).List(context.TODO(), metav1.ListOptions{})
require.NoError(t, err, "failed to get CronJobs")
require.Len(t, cjs.Items, 1)
cj := cjs.Items[0].Spec
require.Equal(t, "0 4 * * MON-FRI", cj.Schedule)
containers := cj.JobTemplate.Spec.Template.Spec.Containers
require.Len(t, containers, 1)
require.Len(t, containers[0].Args, 2)
}

func fakeUpsert(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
pa := action.(clienttesting.PatchAction)
if pa.GetPatchType() == types.ApplyPatchType {
// Apply patches are supposed to upsert, but fake client fails if the object doesn't exist,
// if an apply patch occurs for a deployment that doesn't yet exist, create it.
// However, we already hold the fakeclient lock, so we can't use the front door.
rfunc := clienttesting.ObjectReaction(kubeClient.Tracker())
_, obj, err := rfunc(
clienttesting.NewGetAction(pa.GetResource(), pa.GetNamespace(), pa.GetName()),
)
if kerrors.IsNotFound(err) || obj == nil {
objmeta := metav1.ObjectMeta{
Name: pa.GetName(),
Namespace: pa.GetNamespace(),
}
var newobj runtime.Object
switch pa.GetResource().Resource {
case "configmaps":
newobj = &v1.ConfigMap{ObjectMeta: objmeta}
case "cronjobs":
newobj = &batchv1.CronJob{ObjectMeta: objmeta}
}
_, _, _ = rfunc(
clienttesting.NewCreateAction(
pa.GetResource(),
pa.GetNamespace(),
newobj,
),
)
}
return rfunc(clienttesting.NewPatchAction(
pa.GetResource(),
pa.GetNamespace(),
pa.GetName(),
types.StrategicMergePatchType,
pa.GetPatch()))
}
return false, nil, nil
}

const lighthouseJob = `{"kind":"LighthouseJob","apiVersion":"lighthouse.jenkins.io/v1alpha1","metadata":{"generateName":"testorg-myapp-","creationTimestamp":null,"labels":{"app":"lighthouse-webhooks","component":"periodic","created-by-lighthouse":"true","lighthouse.jenkins-x.io/job":"dailyjob","lighthouse.jenkins-x.io/type":"periodic","repo":"myapp","trigger":"dailyjob"},"annotations":{"lighthouse.jenkins-x.io/job":"dailyjob"}},"spec":{"type":"periodic","agent":"tekton-pipeline","job":"dailyjob","refs":{"org":"testorg","repo":"myapp"},"pipeline_run_spec":{"pipelineSpec":{"tasks":[{"name":"echo-greeting","taskRef":{"name":"task-echo-message"},"params":[{"name":"MESSAGE","value":"$(params.GREETINGS)"},{"name":"BUILD_ID","value":"$(params.BUILD_ID)"},{"name":"JOB_NAME","value":"$(params.JOB_NAME)"},{"name":"JOB_SPEC","value":"$(params.JOB_SPEC)"},{"name":"JOB_TYPE","value":"$(params.JOB_TYPE)"},{"name":"PULL_BASE_REF","value":"$(params.PULL_BASE_REF)"},{"name":"PULL_BASE_SHA","value":"$(params.PULL_BASE_SHA)"},{"name":"PULL_NUMBER","value":"$(params.PULL_NUMBER)"},{"name":"PULL_PULL_REF","value":"$(params.PULL_PULL_REF)"},{"name":"PULL_PULL_SHA","value":"$(params.PULL_PULL_SHA)"},{"name":"PULL_REFS","value":"$(params.PULL_REFS)"},{"name":"REPO_NAME","value":"$(params.REPO_NAME)"},{"name":"REPO_OWNER","value":"$(params.REPO_OWNER)"},{"name":"REPO_URL","value":"$(params.REPO_URL)"}]}],"params":[{"name":"GREETINGS","type":"string","description":"morning greetings, default is Good Morning!","default":"Good Morning!"},{"name":"BUILD_ID","type":"string","description":"the unique build number"},{"name":"JOB_NAME","type":"string","description":"the name of the job which is the trigger context name"},{"name":"JOB_SPEC","type":"string","description":"the specification of the job"},{"name":"JOB_TYPE","type":"string","description":"'the kind of job: postsubmit or presubmit'"},{"name":"PULL_BASE_REF","type":"string","description":"the base git reference of the pull request"},{"name":"PULL_BASE_SHA","type":"string","description":"the git sha of the base of the pull request"},{"name":"PULL_NUMBER","type":"string","description":"git pull request number","default":""},{"name":"PULL_PULL_REF","type":"string","description":"git pull request ref in the form 'refs/pull/$PULL_NUMBER/head'","default":""},{"name":"PULL_PULL_SHA","type":"string","description":"git revision to checkout (branch, tag, sha, ref…)","default":""},{"name":"PULL_REFS","type":"string","description":"git pull reference strings of base and latest in the form 'master:$PULL_BASE_SHA,$PULL_NUMBER:$PULL_PULL_SHA:refs/pull/$PULL_NUMBER/head'"},{"name":"REPO_NAME","type":"string","description":"git repository name"},{"name":"REPO_OWNER","type":"string","description":"git repository owner (user or organisation)"},{"name":"REPO_URL","type":"string","description":"git url to clone"}]}},"pipeline_run_params":[{"name":"GREETINGS"}]},"status":{"startTime":null}}`
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: dailyjob
spec:
pipelineSpec:
params:
- name: GREETINGS
description: "morning greetings, default is Good Morning!"
type: string
default: "Good Morning!"
tasks:
- name: echo-greeting
taskRef:
name: task-echo-message
params:
- name: MESSAGE
value: $(params.GREETINGS)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: config.lighthouse.jenkins-x.io/v1alpha1
kind: TriggerConfig
spec:
periodics:
- name: dailyjob
cron: "0 4 * * MON-FRI"
source: dailyjob.yaml
pipeline_run_params:
- name: GREETINGS
valueTemplate: 'Howdy!'

0 comments on commit 549606f

Please sign in to comment.