Skip to content

Commit

Permalink
Merge pull request #1 from ssttehrani/main
Browse files Browse the repository at this point in the history
refactor: overhaul codebase for bug fix and enhanced functionality
  • Loading branch information
ssttehrani authored Jan 20, 2024
2 parents 7380bc9 + 9956be8 commit 42b3760
Show file tree
Hide file tree
Showing 25 changed files with 6,795 additions and 1,120 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ RUN go mod download
# Copy the go source
COPY cmd/main.go cmd/main.go
COPY internal/ internal/
COPY pkg/ pkg/

# Copy the Makefile
COPY Makefile .
Expand Down
20 changes: 18 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,29 @@ GO_BUILD_LDFLAGS := \
# Image URL to use all building/pushing image targets
IMG ?= $(BIN):$(VERSION)

## Tool Binaries
ENVTEST ?= $(LOCALBIN)/setup-envtest

# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.28.0

## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
mkdir -p $(LOCALBIN)

all: build

test: check

.PHONY: check
check: fmt vet lint
go test ./... -coverprofile cover.out
check: fmt vet lint envtest
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out

.PHONY: envtest
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
$(ENVTEST): $(LOCALBIN)
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest

.PHONY: build
build: fmt vet lint
Expand Down
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,27 @@ When duplicates occur, all the related HTTPProxy objects turn invalid, leading t
## How It Works

### Overview:
The `contour-admission-webhook` server relies on an in-memory cache, initialized at startup, to maintain a map of FQDNs to their respective owner references before it begins processing requests. At the forefront of the rule chain is the FQDN validation rule, which leverages this in-memory cache.
The `contour-admission-webhook` server relies on an in-memory cache, initialized at startup, to maintain a map of FQDNs to their respective owner references before it begins processing requests. Among the rules within the rule chain, the FQDN validation rule specifically utilizes this in-memory cache.

### IngressClassName Validation Flow:
- CREATE/UPDATE Operations:

When creating or updating an HTTPProxy object, it is a requirement that the value specified for `spec.ingressClassName` must correspond to one of the configured ingressClassNames. Additionally, the `spec.ingressClassName` cannot be an empty string.

- DELETE Operations:

Upon executing a DELETE operation, the validation for `spec.ingressClassName` is not enforced. The deletion process does not involve the validation of the `spec.ingressClassName` value, allowing for the removal of the corresponding HTTPProxy object without considering this specific parameter.

### FQDN Validation Flow:
- CREATE/UPDATE Operations:

When attempting to create or update an HTTPProxy object, the webhook first checks the requested FQDN against the built-in cache. If a match is found, the webhook operation is declined, accompanied by a message detailing the reason.
If no match is found, the FQDN is added to the cache and the operation gets approved.
For UPDATE operations specifically, any previous FQDN associated with the object is removed from the cache.
If no match is found, the FQDN is added to the cache with a TTL, and the operation gets approved. A TTL mechanism is implemented to prevent the persistence of invalid states in the cache, ensuring timely removal upon rejection in other validating webhooks. After persisting in the state storage (etcd), the TTL is removed by a Kubernetes controller which watches HTTPProxy objects.
For UPDATE operations specifically, any previous FQDN associated with the object is removed from the cache by a Kubernetes controller. This cleanup occurs after the object is persisted in the state storage (etcd).

- DELETE Operations:

Upon executing a DELETE operation, the corresponding FQDN entry is purged from the cache and the operation gets approved.
Upon executing a DELETE operation, the operation gets approved and the corresponding FQDN entry is purged from the cache after the object is persisted in the state storage (etcd).

<!-- ## Getting Started -->

Expand Down Expand Up @@ -67,3 +76,11 @@ The rule chain contains rules that are executed in the order set to validate the
4. Add your rule to the chain:

Modify the chain initialiser in include your rule.

## To Do

Below is a list of tasks that need attention. If you're contributing to this project or managing it, this section serves as a quick reference for ongoing and upcoming work.
- Add Helm chart
- Make cache key configurable
- Implement a mechanism to warm up the controller cache before launching the webhook server
- Add E2E tests
87 changes: 74 additions & 13 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,96 @@ package main

import (
"flag"
"os"
"time"

contourv1 "github.com/projectcontour/contour/apis/projectcontour/v1"
"github.com/snapp-incubator/contour-admission-webhook/internal/cache"
"github.com/snapp-incubator/contour-admission-webhook/internal/client"
"github.com/snapp-incubator/contour-admission-webhook/internal/config"
controller "github.com/snapp-incubator/contour-admission-webhook/internal/controller/httpproxy"
"github.com/snapp-incubator/contour-admission-webhook/internal/webhook"
"k8s.io/klog/v2"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

var (
scheme = runtime.NewScheme()
logger = ctrl.Log.WithName("setup")
)

func init() {
klog.InitFlags(nil)
utilruntime.Must(contourv1.AddToScheme(scheme))
}

func main() {
var address, tlsKeyPath, tlsCertPath string
ctrl.SetLogger(zap.New())

var configFilePath string

flag.StringVar(&address, "address", ":8443", "Server listen address")
flag.StringVar(&tlsKeyPath, "tls-key-path", "./tls.key", "Path to the TLS key")
flag.StringVar(&tlsCertPath, "tls-cert-path", "./tls.crt", "Path to the TLS certificate")
flag.StringVar(&configFilePath, "config-file-path", "./config.yaml", "The config file path.")
flag.Parse()

client, err := client.NewK8sClient()
logger.Info("initializing config")

if err := config.InitializeConfig(configFilePath); err != nil {
logger.Error(err, "error reading the config file")

os.Exit(1)
}

logger.Info("initializing cache")

cfg := config.GetConfig()

cache := cache.NewCache(time.Duration(cfg.Cache.CleanUpIntervalSecond) * time.Second)

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
LeaderElection: false,
})
if err != nil {
klog.Fatalf("K8s client setup failed: %s", err)
logger.Error(err, "unable to create manager")

os.Exit(1)
}

cache := cache.NewCache()
reconcilerExtended := controller.NewReconcilerExtended(mgr, cache)

if err := cache.PopulateInitialCache(client); err != nil {
klog.Fatalf("Cache initialization failed: %s", err)
if err = reconcilerExtended.SetupWithManager(mgr); err != nil {
logger.Error(err, "unable to set up the controller with the manager", "controller", "httpproxy")

os.Exit(1)
}

webhook.Setup(address, tlsCertPath, tlsKeyPath, cache)
errChan := make(chan error)

ctx := ctrl.SetupSignalHandler()

go func() {
logger.Info("starting controller(s)")

if err := mgr.Start(ctx); err != nil {
errChan <- err
}

errChan <- nil
}()

// This call is non-blocking.
webhookStoppedCh, webhookListenerStoppedCh := webhook.Setup(cache)

select {
case err := <-errChan:
logger.Error(err, "encountered error; exited")

os.Exit(1)
case <-ctx.Done():
<-webhookStoppedCh

<-webhookListenerStoppedCh

os.Exit(0)
}
}
78 changes: 73 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,128 @@ go 1.21.3
replace github.com/projectcontour/contour => github.com/snapp-incubator/contour v1.2.1-0.20231022200816-a6fdb4afdd9f

require (
github.com/go-logr/logr v1.2.4
github.com/json-iterator/go v1.1.12
github.com/labstack/echo/v4 v4.11.2
github.com/onsi/ginkgo/v2 v2.13.0
github.com/onsi/gomega v1.28.0
github.com/projectcontour/contour v0.0.0-00010101000000-000000000000
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.4
k8s.io/api v0.28.3
k8s.io/apimachinery v0.28.3
k8s.io/klog/v2 v2.100.1
k8s.io/apiserver v0.28.3
k8s.io/client-go v0.28.3
sigs.k8s.io/controller-runtime v0.16.3
)

require (
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/cel-go v0.16.1 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
go.etcd.io/etcd/api/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/v3 v3.5.9 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 // indirect
go.opentelemetry.io/otel v1.10.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 // indirect
go.opentelemetry.io/otel/metric v0.31.0 // indirect
go.opentelemetry.io/otel/sdk v1.10.0 // indirect
go.opentelemetry.io/otel/trace v1.10.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.13.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832 // indirect
google.golang.org/grpc v1.58.3 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/client-go v0.28.3 // indirect
k8s.io/apiextensions-apiserver v0.28.3 // indirect
k8s.io/component-base v0.28.3 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kms v0.28.3 // indirect
k8s.io/kube-openapi v0.0.0-20230905202853-d090da108d2f // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
Expand Down
Loading

0 comments on commit 42b3760

Please sign in to comment.