Skip to content
This repository has been archived by the owner on Apr 18, 2024. It is now read-only.

Commit

Permalink
Merge pull request #15 from flanksource/e2e-tests
Browse files Browse the repository at this point in the history
E2e tests for copy-to-namespace and awx operator
  • Loading branch information
moshloop authored Jan 13, 2021
2 parents 82222e6 + 1baa7ad commit c64fe88
Show file tree
Hide file tree
Showing 21 changed files with 1,984 additions and 695 deletions.
567 changes: 284 additions & 283 deletions config/crd/bases/templating.flanksource.com_templates.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions config/default/manager_auth_proxy_patch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ spec:
args:
- "--metrics-addr=127.0.0.1:8080"
- "--enable-leader-election"
- "--sync-period=20s"
393 changes: 197 additions & 196 deletions config/deploy/crd.yml

Large diffs are not rendered by default.

394 changes: 198 additions & 196 deletions config/deploy/operator.yml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions controllers/template_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type TemplateReconciler struct {
Client *kommons.Client
Log logr.Logger
Scheme *runtime.Scheme
Cache *k8s.SchemaCache
}

// +kubebuilder:rbac:groups="*",resources="*",verbs="*"
Expand All @@ -54,14 +55,13 @@ func (r *TemplateReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
return reconcile.Result{}, err
}

tm, err := k8s.NewTemplateManager(r.Client, log)
tm, err := k8s.NewTemplateManager(r.Client, log, r.Cache)
if err != nil {
return reconcile.Result{}, err
}
if err := tm.Run(ctx, template); err != nil {
return reconcile.Result{}, err
}

return ctrl.Result{}, nil
}

Expand Down
7 changes: 7 additions & 0 deletions examples/namespace-request-a.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: acmp.corp/v1
kind: NamespaceRequest
metadata:
name: a
spec:
team: blue-team
memory: 16
9 changes: 0 additions & 9 deletions examples/namespacerequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ spec:
- name: v1
served: true
storage: true

---
apiVersion: acmp.corp/v1
kind: NamespaceRequest
metadata:
name: a
spec:
team: blue-team
memory: 16
---
apiVersion: templating.flanksource.com/v1
kind: Template
Expand Down
3 changes: 1 addition & 2 deletions examples/postgres-operator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,7 @@ spec:
ttl: 30
podAnnotations: {}
postgresql:
parameters:
log_destination: stderr
parameters: "{{ .spec.parameters | default (coll.Dict) | data.ToJSON }}"
version: "12"
resources:
limits:
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ require (
github.com/onsi/gomega v1.10.1
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.7.0
github.com/sykesm/zap-logfmt v0.0.4
github.com/tidwall/gjson v1.6.1
golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5 // indirect
github.com/zalando/postgres-operator v1.6.0
go.uber.org/zap v1.15.0
gopkg.in/flanksource/yaml.v3 v3.1.1
k8s.io/api v0.19.4
k8s.io/apiextensions-apiserver v0.19.4
Expand Down
42 changes: 42 additions & 0 deletions go.sum

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions k8s/patches.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,16 @@ func (p *PatchApplier) JSONPath(object interface{}, jsonpath string) string {
value := gjson.Get(string(jsonObject), jsonpath)
return value.String()
}

var annotationsBlacklist = []string{
"metadata.annotations.serving.knative.dev/creator",
"metadata.annotations.serving.knative.dev/lastModifier",
}

func stripAnnotations(obj *unstructured.Unstructured) {
annotations := obj.GetAnnotations()
for _, a := range annotationsBlacklist {
delete(annotations, a)
}
obj.SetAnnotations(annotations)
}
95 changes: 95 additions & 0 deletions k8s/schema_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package k8s

import (
"context"
"encoding/json"
"sync"
"time"

"github.com/go-logr/logr"
"github.com/go-openapi/spec"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)

type SchemaCache struct {
clientset *kubernetes.Clientset
expire time.Duration
lock *sync.Mutex

resources []*metav1.APIResourceList
resourcesExpireTimestamp time.Time

schema *spec.Swagger
schemaExpireTimestamp time.Time
log logr.Logger
}

func NewSchemaCache(clientset *kubernetes.Clientset, expire time.Duration, log logr.Logger) *SchemaCache {
sc := &SchemaCache{
clientset: clientset,
expire: expire,
lock: &sync.Mutex{},
log: log,

resources: nil,
}
return sc
}

func (sc *SchemaCache) FetchSchema() (*spec.Swagger, error) {
sc.lock.Lock()
defer sc.lock.Unlock()

if sc.resources == nil || time.Now().After(sc.schemaExpireTimestamp) {
sc.log.V(2).Info("before fetch schema")
if err := sc.fetchAndSetSchema(); err != nil {
return nil, errors.Wrap(err, "failed to refetch API schema")
}
sc.log.V(2).Info("after fetch schema")
}

return sc.schema, nil
}

func (sc *SchemaCache) FetchResources() ([]*metav1.APIResourceList, error) {
sc.lock.Lock()
defer sc.lock.Unlock()

if sc.resources == nil || time.Now().After(sc.resourcesExpireTimestamp) {
sc.log.V(2).Info("before fetch resources")
if err := sc.fetchAndSetResources(); err != nil {
return nil, errors.Wrap(err, "failed to refetch API resources")
}
sc.log.V(2).Info("after fetch resources")
}
return sc.resources, nil
}

func (sc *SchemaCache) fetchAndSetSchema() error {
bs, err := sc.clientset.RESTClient().Get().AbsPath("openapi", "v2").DoRaw(context.TODO())
if err != nil {
return errors.Wrap(err, "failed to fetch schema from server")
}
s := &spec.Swagger{}

if err := json.Unmarshal(bs, &s); err != nil {
return errors.Wrap(err, "failed to unmarshal openapi")
}

sc.schema = s
sc.schemaExpireTimestamp = time.Now().Add(sc.expire)

return nil
}

func (sc *SchemaCache) fetchAndSetResources() error {
serverResources, err := sc.clientset.ServerResources()
if err != nil {
return errors.Wrap(err, "failed to list server resources")
}
sc.resources = serverResources
sc.resourcesExpireTimestamp = time.Now().Add(sc.expire)
return nil
}
20 changes: 20 additions & 0 deletions k8s/schema_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,26 @@ type TypedField struct {

type MapInterface map[string]interface{}

func NewSchemaManagerWithCache(clientset *kubernetes.Clientset, crdClient extapi.ApiextensionsV1beta1Interface, cache *SchemaCache) (*SchemaManager, error) {
s, err := cache.FetchSchema()
if err != nil {
return nil, err
}

serverResources, err := cache.FetchResources()
if err != nil {
return nil, errors.Wrap(err, "failed to list server resources")
}

mgr := &SchemaManager{
swagger: s,
serverResources: serverResources,
clientset: clientset,
crdClient: crdClient,
}
return mgr, nil
}

func NewSchemaManager(clientset *kubernetes.Clientset, crdClient extapi.ApiextensionsV1beta1Interface) (*SchemaManager, error) {
bs, err := clientset.RESTClient().Get().AbsPath("openapi", "v2").DoRaw(context.TODO())
if err != nil {
Expand Down
8 changes: 6 additions & 2 deletions k8s/template_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type ResourcePatch struct {
PatchType PatchType
}

func NewTemplateManager(c *kommons.Client, log logr.Logger) (*TemplateManager, error) {
func NewTemplateManager(c *kommons.Client, log logr.Logger, cache *SchemaCache) (*TemplateManager, error) {
clientset, _ := c.GetClientset()

restConfig, err := c.GetRESTConfig()
Expand All @@ -56,7 +56,7 @@ func NewTemplateManager(c *kommons.Client, log logr.Logger) (*TemplateManager, e
return nil, errors.Wrap(err, "failed to create crd client")
}

schemaManager, err := NewSchemaManager(clientset, crdClient)
schemaManager, err := NewSchemaManagerWithCache(clientset, crdClient, cache)
if err != nil {
return nil, errors.Wrap(err, "failed to create schema manager")
}
Expand Down Expand Up @@ -153,6 +153,7 @@ func (tm *TemplateManager) Run(ctx context.Context, template *templatev1.Templat
}
if len(template.Spec.JsonPatches) > 0 || len(template.Spec.Patches) > 0 {
target = markApplied(template, target)
stripAnnotations(target)
if err := tm.Client.ApplyUnstructured(source.GetNamespace(), target); err != nil {
return err
}
Expand All @@ -177,6 +178,8 @@ func (tm *TemplateManager) Run(ctx context.Context, template *templatev1.Templat
crossNamespaceOwner(&obj, source)
}

stripAnnotations(&obj)

if tm.Log.V(2).Enabled() {
tm.Log.V(2).Info("Applying", "kind", obj.GetKind(), "namespace", obj.GetNamespace(), "name", obj.GetName(), "obj", obj)
} else {
Expand All @@ -192,6 +195,7 @@ func (tm *TemplateManager) Run(ctx context.Context, template *templatev1.Templat
for _, namespace := range template.Spec.CopyToNamespaces.Namespaces {
newResource := source.DeepCopy()
newResource.SetNamespace(namespace)
stripAnnotations(newResource)

crossNamespaceOwner(newResource, source)

Expand Down
4 changes: 3 additions & 1 deletion k8s/template_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package k8s_test
import (
"fmt"
"strings"
"time"

"github.com/flanksource/template-operator/k8s"
. "github.com/onsi/ginkgo"
Expand Down Expand Up @@ -69,7 +70,8 @@ spec:
synchronous_mode: false
`

templateManager, err := k8s.NewTemplateManager(kommonsClient(), testLog)
cache := k8s.NewSchemaCache(clientset(), 5*time.Minute, testLog)
templateManager, err := k8s.NewTemplateManager(kommonsClient(), testLog, cache)
Expect(err).ToNot(HaveOccurred())

result, err := templateManager.Template([]byte(templateJSON), db)
Expand Down
29 changes: 26 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import (
"github.com/flanksource/kommons"
templatingflanksourcecomv1 "github.com/flanksource/template-operator/api/v1"
"github.com/flanksource/template-operator/controllers"
"github.com/flanksource/template-operator/k8s"
zaplogfmt "github.com/sykesm/zap-logfmt"
uzap "go.uber.org/zap"
"go.uber.org/zap/zapcore"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
Expand All @@ -45,11 +49,23 @@ func init() {
// +kubebuilder:scaffold:scheme
}

func setupLogger(opts zap.Options) {
configLog := uzap.NewProductionEncoderConfig()
configLog.EncodeTime = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(ts.UTC().Format(time.RFC3339Nano))
}
logfmtEncoder := zaplogfmt.NewEncoder(configLog)

logger := zap.New(zap.UseFlagOptions(&opts), zap.Encoder(logfmtEncoder))
ctrl.SetLogger(logger)
}

func main() {
var metricsAddr string
var enableLeaderElection bool
var syncPeriod time.Duration
flag.DurationVar(&syncPeriod, "sync-period", 5*time.Minute, "The time duration to run a full reconcole")
var syncPeriod, expire time.Duration
flag.DurationVar(&syncPeriod, "sync-period", 5*time.Minute, "The time duration to run a full reconcile")
flag.DurationVar(&expire, "expire", 15*time.Minute, "The time duration to expire API resources cache")
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
"Enable leader election for controller manager. "+
Expand All @@ -58,7 +74,7 @@ func main() {
opts := zap.Options{}
opts.BindFlags(flag.CommandLine)
flag.Parse()
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
setupLogger(opts)

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Expand All @@ -74,9 +90,16 @@ func main() {
}

client := kommons.NewClient(mgr.GetConfig(), logger.StandardLogger())
clientset, err := client.GetClientset()
if err != nil {
setupLog.Error(err, "failed to get clientset")
os.Exit(1)
}
schemaCache := k8s.NewSchemaCache(clientset, expire, ctrl.Log.WithName("schema-cache"))

if err = (&controllers.TemplateReconciler{
Client: client,
Cache: schemaCache,
Log: ctrl.Log.WithName("controllers").WithName("Template"),
Scheme: mgr.GetScheme(),
}).SetupWithManager(mgr); err != nil {
Expand Down
6 changes: 6 additions & 0 deletions test/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ s3:
skipTLSVerify: true
e2e:
minio: true
minio:
version: RELEASE.2020-09-02T18-19-50Z
access_key: minio
secret_key: minio123
replicas: 1
ca:
cert: .certs/root-ca.crt
privateKey: .certs/root-ca.key
Expand All @@ -44,6 +49,7 @@ canaryChecker:
version: v0.11.2
postgresOperator:
version: v1.3.4.flanksource.1
backupBucket: e2e-postgres-backups
test:
exclude:
- configmap-reloader
Expand Down
Loading

0 comments on commit c64fe88

Please sign in to comment.