Skip to content
This repository has been archived by the owner on Oct 12, 2023. It is now read-only.

add requeueAfter option #51

Merged
merged 2 commits into from
Sep 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions api/v1alpha1/applicationset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ type ClusterGenerator struct {
}

type GitGenerator struct {
RepoURL string `json:"repoURL"`
Directories []GitDirectoryGeneratorItem `json:"directories,omitempty"`
Revision string `json:"revision"`
RepoURL string `json:"repoURL"`
Directories []GitDirectoryGeneratorItem `json:"directories,omitempty"`
Revision string `json:"revision"`
RequeueAfterSeconds int64 `json:"requeueAfterSeconds,omitempty"`
}

type GitDirectoryGeneratorItem struct {
Expand Down
8 changes: 4 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ func main() {
k8s := kubernetes.NewForConfigOrDie(mgr.GetConfig())

if err = (&controllers.ApplicationSetReconciler{
Generators: []generators.Generator{
generators.NewListGenerator(),
generators.NewClusterGenerator(mgr.GetClient()),
generators.NewGitGenerator(services.NewArgoCDService(context.Background(), k8s, namespace, argocdRepoServer)),
Generators: map[string]generators.Generator{
"List": generators.NewListGenerator(),
"Clusters": generators.NewClusterGenerator(mgr.GetClient()),
"Git": generators.NewGitGenerator(services.NewArgoCDService(context.Background(), k8s, namespace, argocdRepoServer)),
},
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Expand Down
3 changes: 3 additions & 0 deletions manifests/crds/applicationset-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ spec:
type: string
revision:
type: string
requeueAfterSeconds:
format: int64
type: integer
required:
- repoURL
- revision
Expand Down
52 changes: 49 additions & 3 deletions pkg/controllers/applicationset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/record"
"k8s.io/kubernetes/pkg/apis/core"
"reflect"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/source"
"time"

log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -43,7 +45,7 @@ type ApplicationSetReconciler struct {
client.Client
Scheme *runtime.Scheme
Recorder record.EventRecorder
Generators []generators.Generator
Generators map[string]generators.Generator
utils.Policy
utils.Renderer
}
Expand Down Expand Up @@ -89,7 +91,50 @@ func (r *ApplicationSetReconciler) Reconcile(req ctrl.Request) (ctrl.Result, err
}
}

return ctrl.Result{}, nil
requeueAfter := r.getMinRequeueAfter(&applicationSetInfo)
log.WithField("requeueAfter", requeueAfter).Info("end reconcile")

return ctrl.Result{
RequeueAfter: requeueAfter,
}, nil
}

func (r *ApplicationSetReconciler) GetRelevantGenerators(requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator) []generators.Generator{
var res []generators.Generator

v := reflect.Indirect(reflect.ValueOf(requestedGenerator))
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
if !field.CanInterface() {
continue
}

if !reflect.ValueOf(field.Interface()).IsNil() {
res = append(res, r.Generators[v.Type().Field(i).Name])
}
}

return res
}

func (r *ApplicationSetReconciler) getMinRequeueAfter(applicationSetInfo *argoprojiov1alpha1.ApplicationSet) time.Duration{
var res time.Duration
for _, requestedGenerator := range applicationSetInfo.Spec.Generators {

generators := r.GetRelevantGenerators(&requestedGenerator)

for _, g := range generators {
t := g.GetRequeueAfter(&requestedGenerator)

if res == 0 {
res = t
} else if t != 0 && t < res {
res = t
}
}
}

return res
}

func getTempApplication(applicationSetTemplate argoprojiov1alpha1.ApplicationSetTemplate) *argov1alpha1.Application{
Expand All @@ -108,7 +153,8 @@ func (r *ApplicationSetReconciler) generateApplications(applicationSetInfo argop
var firstError error
tmplApplication := getTempApplication(applicationSetInfo.Spec.Template)
for _, requestedGenerator := range applicationSetInfo.Spec.Generators {
for _, g := range r.Generators {
generators := r.GetRelevantGenerators(&requestedGenerator)
for _, g := range generators {
params, err := g.GenerateParams(&requestedGenerator)
if err != nil {
log.WithError(err).WithField("generator", g).
Expand Down
57 changes: 55 additions & 2 deletions pkg/controllers/applicationset_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"testing"
"time"

argoprojiov1alpha1 "github.com/argoproj-labs/applicationset/api/v1alpha1"
)
Expand All @@ -33,6 +34,12 @@ type rendererMock struct {
mock.Mock
}

func (g *generatorMock) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration {
args := g.Called(appSetGenerator)

return args.Get(0).(time.Duration)
}

func (r *rendererMock) RenderTemplateParams(tmpl *argov1alpha1.Application, params map[string]string) (*argov1alpha1.Application, error) {
args := r.Called(tmpl, params)

Expand Down Expand Up @@ -134,8 +141,8 @@ func TestExtractApplications(t *testing.T) {
Client: client,
Scheme: scheme,
Recorder: record.NewFakeRecorder(1),
Generators: []generators.Generator{
&generatorMock,
Generators: map[string]generators.Generator{
"List": &generatorMock,
},
Renderer: &rendererMock,
}
Expand Down Expand Up @@ -683,5 +690,51 @@ func TestDeleteInCluster(t *testing.T) {
assert.EqualError(t, err, fmt.Sprintf("applications.argoproj.io \"%s\" not found", obj.Name))
}
}
}

func TestGetMinRequeueAfter(t *testing.T) {
scheme := runtime.NewScheme()
argoprojiov1alpha1.AddToScheme(scheme)
argov1alpha1.AddToScheme(scheme)


client := fake.NewFakeClientWithScheme(scheme)

generator := argoprojiov1alpha1.ApplicationSetGenerator{
List: &argoprojiov1alpha1.ListGenerator{},
Git: &argoprojiov1alpha1.GitGenerator{},
Clusters: &argoprojiov1alpha1.ClusterGenerator{},
}

generatorMock0 := generatorMock{}
generatorMock0.On("GetRequeueAfter", &generator).
Return(generators.NoRequeueAfter)

generatorMock1 := generatorMock{}
generatorMock1.On("GetRequeueAfter", &generator).
Return(time.Duration(1) * time.Second)

generatorMock10 := generatorMock{}
generatorMock10.On("GetRequeueAfter", &generator).
Return(time.Duration(10) * time.Second)

r := ApplicationSetReconciler{
Client: client,
Scheme: scheme,
Recorder: record.NewFakeRecorder(0),
Generators: map[string]generators.Generator{
"List": &generatorMock10,
"Git": &generatorMock1,
"Clusters": &generatorMock1,
},
}


got := r.getMinRequeueAfter(&argoprojiov1alpha1.ApplicationSet{
Spec: argoprojiov1alpha1.ApplicationSetSpec{
Generators: []argoprojiov1alpha1.ApplicationSetGenerator{generator},
},
},)

assert.Equal(t, time.Duration(1) * time.Second, got)
}
5 changes: 5 additions & 0 deletions pkg/generators/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package generators
import (
"context"
"fmt"
"time"

log "github.com/sirupsen/logrus"

Expand Down Expand Up @@ -33,6 +34,10 @@ func NewClusterGenerator(c client.Client) Generator {
return g
}

func (g * ClusterGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration {
return NoRequeueAfter
}

func (g *ClusterGenerator) GenerateParams(
appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) ([]map[string]string, error) {

Expand Down
5 changes: 5 additions & 0 deletions pkg/generators/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/argoproj-labs/applicationset/pkg/services"
log "github.com/sirupsen/logrus"
"path"
"time"
)

var _ Generator = (*GitGenerator)(nil)
Expand All @@ -21,6 +22,10 @@ func NewGitGenerator(repos services.Apps) Generator {
return g
}

func (g * GitGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration {
return time.Duration(appSetGenerator.Git.RequeueAfterSeconds) * time.Second
}

func (g *GitGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) ([]map[string]string, error) {

if appSetGenerator == nil {
Expand Down
15 changes: 11 additions & 4 deletions pkg/generators/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ package generators
import (
"errors"
argoprojiov1alpha1 "github.com/argoproj-labs/applicationset/api/v1alpha1"
"time"
)



// Generator defines the interface implemented by all ApplicationSet generators.
type Generator interface {
// GenerateParams interprets the ApplicationSet and generates all relevant parameters for the application template.
// This function will be called for every generator,
//even if there isn't any application - in this case the result should be nil without an error
// The expected / desired list of parameters is returned, it then needs to be render and reconciled
// The expected / desired list of parameters is returned, it then will be render and reconciled
// against the current state of the Applications in the cluster.
GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) ([]map[string]string, error)

// GetRequeueAfter is the the generator can controller the next reconciled loop
// In case there is more then one generator the time will be the minimum of the times.
// In case NoRequeueAfter is empty, it will be ignored
GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration
}

var EmptyAppSetGeneratorError = errors.New("ApplicationSet is empty")
var EmptyAppSetGeneratorError = errors.New("ApplicationSet is empty")
var NoRequeueAfter time.Duration
5 changes: 5 additions & 0 deletions pkg/generators/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package generators
import (
argoprojiov1alpha1 "github.com/argoproj-labs/applicationset/api/v1alpha1"
"github.com/argoproj-labs/applicationset/pkg/utils"
"time"
)

var _ Generator = (*ListGenerator)(nil)
Expand All @@ -16,6 +17,10 @@ func NewListGenerator() Generator {
return g
}

func (g * ListGenerator) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) time.Duration {
return NoRequeueAfter
}

func (g *ListGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha1.ApplicationSetGenerator) ([]map[string]string, error) {
if appSetGenerator == nil {
return nil, EmptyAppSetGeneratorError
Expand Down