1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00
kyverno/pkg/webhooks/generate/generate.go
Shivkumar Dudhani 8c1d79ab28
linter suggestions (#655)
* cleanup phase 1

* linter fixes phase 2
2020-01-24 12:05:53 -08:00

118 lines
3.1 KiB
Go

package generate
import (
"fmt"
"time"
backoff "github.com/cenkalti/backoff"
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
)
//GenerateRequests provides interface to manage generate requests
type GenerateRequests interface {
Create(gr kyverno.GenerateRequestSpec) error
}
// Generator defines the implmentation to mange generate request resource
type Generator struct {
// channel to receive request
ch chan kyverno.GenerateRequestSpec
client *kyvernoclient.Clientset
stopCh <-chan struct{}
}
//NewGenerator returns a new instance of Generate-Request resource generator
func NewGenerator(client *kyvernoclient.Clientset, stopCh <-chan struct{}) *Generator {
gen := &Generator{
ch: make(chan kyverno.GenerateRequestSpec, 1000),
client: client,
stopCh: stopCh,
}
return gen
}
//Create to create generate request resoruce (blocking call if channel is full)
func (g *Generator) Create(gr kyverno.GenerateRequestSpec) error {
glog.V(4).Infof("create GR %v", gr)
// Send to channel
select {
case g.ch <- gr:
return nil
case <-g.stopCh:
glog.Info("shutting down channel")
return fmt.Errorf("shutting down gr create channel")
}
}
// Run starts the generate request spec
func (g *Generator) Run(workers int) {
defer utilruntime.HandleCrash()
glog.V(4).Info("Started generate request")
defer func() {
glog.V(4).Info("Shutting down generate request")
}()
for i := 0; i < workers; i++ {
go wait.Until(g.process, time.Second, g.stopCh)
}
<-g.stopCh
}
func (g *Generator) process() {
for r := range g.ch {
glog.V(4).Infof("received generate request %v", r)
if err := g.generate(r); err != nil {
glog.Errorf("Failed to create Generate Request CR: %v", err)
}
}
}
func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec) error {
// create a generate request
if err := retryCreateResource(g.client, grSpec); err != nil {
return err
}
return nil
}
// -> receiving channel to take requests to create request
// use worker pattern to read and create the CR resource
func retryCreateResource(client *kyvernoclient.Clientset, grSpec kyverno.GenerateRequestSpec) error {
var i int
var err error
createResource := func() error {
gr := kyverno.GenerateRequest{
Spec: grSpec,
}
gr.SetGenerateName("gr-")
gr.SetNamespace("kyverno")
// Initial state "Pending"
// TODO: status is not updated
// gr.Status.State = kyverno.Pending
// generate requests created in kyverno namespace
_, err = client.KyvernoV1().GenerateRequests("kyverno").Create(&gr)
glog.V(4).Infof("retry %v create generate request", i)
i++
return err
}
exbackoff := &backoff.ExponentialBackOff{
InitialInterval: 500 * time.Millisecond,
RandomizationFactor: 0.5,
Multiplier: 1.5,
MaxInterval: time.Second,
MaxElapsedTime: 3 * time.Second,
Clock: backoff.SystemClock,
}
exbackoff.Reset()
err = backoff.Retry(createResource, exbackoff)
if err != nil {
return err
}
return nil
}