mirror of
https://github.com/eliasstepanik/caddy-ingess.git
synced 2026-01-11 12:38:27 +00:00
init
This commit is contained in:
commit
835b4c018c
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.DS_Store
|
||||||
|
bin
|
||||||
|
vendor
|
||||||
3
Dockerfile
Normal file
3
Dockerfile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
FROM scratch
|
||||||
|
COPY ./bin/ingress-controller .
|
||||||
|
ENTRYPOINT ["/ingress-controller"]
|
||||||
6
Makefile
Normal file
6
Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
build:
|
||||||
|
@mkdir -p bin
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./bin/ingress-controller ./cmd/caddy
|
||||||
|
|
||||||
|
publish-docker:
|
||||||
|
@echo 'TODO :- not implemented'
|
||||||
132
cmd/caddy/main.go
Normal file
132
cmd/caddy/main.go
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/lightcodelabs/ingress/internal/controller"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/apimachinery/pkg/version"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
"k8s.io/klog"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// High enough QPS to fit all expected use cases. QPS=0 is not set here, because
|
||||||
|
// client code is overriding it.
|
||||||
|
defaultQPS = 1e6
|
||||||
|
|
||||||
|
// High enough Burst to fit all expected use cases. Burst=0 is not set here, because
|
||||||
|
// client code is overriding it.
|
||||||
|
defaultBurst = 1e6
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
klog.InitFlags(nil)
|
||||||
|
|
||||||
|
// get the namespace to monitor ingress resources for
|
||||||
|
namespace := os.Getenv("KUBERNETES_NAMESPACE")
|
||||||
|
if len(namespace) == 0 {
|
||||||
|
namespace = v1.NamespaceAll
|
||||||
|
klog.Warning("KUBERNETES_NAMESPACE is unset, will monitor ingresses in all namespaces.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO :- implement
|
||||||
|
// parse any flags required to configure the caddy ingress controller
|
||||||
|
// cfg, err := parseFlags()
|
||||||
|
// if err != nil {
|
||||||
|
// klog.Fatal(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// get client to access the kubernetes service api
|
||||||
|
kubeClient, err := createApiserverClient()
|
||||||
|
if err != nil {
|
||||||
|
msg := `
|
||||||
|
Error while initiating a connection to the Kubernetes API server.
|
||||||
|
This could mean the cluster is misconfigured (e.g. it has invalid API server certificates or Service Accounts configuration)
|
||||||
|
`
|
||||||
|
|
||||||
|
klog.Fatalf(msg, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var resource = "ingresses"
|
||||||
|
restClient := kubeClient.ExtensionsV1beta1().RESTClient()
|
||||||
|
|
||||||
|
// start ingress controller
|
||||||
|
c := controller.NewCaddyController(namespace, kubeClient, resource, restClient)
|
||||||
|
|
||||||
|
// TODO :-
|
||||||
|
// create http server to expose controller health metrics
|
||||||
|
|
||||||
|
klog.Info("Starting the caddy ingress controller")
|
||||||
|
|
||||||
|
// start the ingress controller
|
||||||
|
stopCh := make(chan struct{}, 1)
|
||||||
|
defer close(stopCh)
|
||||||
|
|
||||||
|
go c.Run(stopCh)
|
||||||
|
|
||||||
|
select {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// createApiserverClient creates a new Kubernetes REST client. We assume the
|
||||||
|
// controller runs inside Kubernetes and use the in-cluster config.
|
||||||
|
func createApiserverClient() (*kubernetes.Clientset, error) {
|
||||||
|
cfg, err := clientcmd.BuildConfigFromFlags("", "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.QPS = defaultQPS
|
||||||
|
cfg.Burst = defaultBurst
|
||||||
|
cfg.ContentType = "application/vnd.kubernetes.protobuf"
|
||||||
|
|
||||||
|
klog.Infof("Creating API client for %s", cfg.Host)
|
||||||
|
|
||||||
|
client, err := kubernetes.NewForConfig(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The client may fail to connect to the API server in the first request
|
||||||
|
defaultRetry := wait.Backoff{
|
||||||
|
Steps: 10,
|
||||||
|
Duration: 1 * time.Second,
|
||||||
|
Factor: 1.5,
|
||||||
|
Jitter: 0.1,
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.V(2).Info("Trying to discover Kubernetes version")
|
||||||
|
|
||||||
|
var v *version.Info
|
||||||
|
var retries int
|
||||||
|
var lastErr error
|
||||||
|
err = wait.ExponentialBackoff(defaultRetry, func() (bool, error) {
|
||||||
|
v, err = client.Discovery().ServerVersion()
|
||||||
|
if err == nil {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
lastErr = err
|
||||||
|
klog.V(2).Infof("Unexpected error discovering Kubernetes version (attempt %v): %v", retries, err)
|
||||||
|
retries++
|
||||||
|
return false, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
// err is returned in case of timeout in the exponential backoff (ErrWaitTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, lastErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should not happen, warn the user
|
||||||
|
if retries > 0 {
|
||||||
|
klog.Warningf("Initial connection to the Kubernetes API server was retried %d times.", retries)
|
||||||
|
}
|
||||||
|
|
||||||
|
msg := "Running in Kubernetes cluster version v%v.%v (%v) - git (%v) commit %v - platform %v"
|
||||||
|
klog.Infof(msg, v.Major, v.Minor, v.GitVersion, v.GitTreeState, v.GitCommit, v.Platform)
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
31
go.mod
Normal file
31
go.mod
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
module bitbucket.org/lightcodelabs/ingress
|
||||||
|
|
||||||
|
go 1.12
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gogo/protobuf v1.2.1 // indirect
|
||||||
|
github.com/golang/protobuf v1.3.1 // indirect
|
||||||
|
github.com/google/gofuzz v1.0.0 // indirect
|
||||||
|
github.com/googleapis/gnostic v0.2.0 // indirect
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1 // indirect
|
||||||
|
github.com/imdario/mergo v0.3.7 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.6 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||||
|
github.com/openshift/api v3.9.0+incompatible // indirect
|
||||||
|
github.com/sirupsen/logrus v1.4.1 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.3
|
||||||
|
github.com/stakater/IngressMonitorController v1.0.62
|
||||||
|
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a // indirect
|
||||||
|
golang.org/x/net v0.0.0-20190415100556-4a65cf94b679 // indirect
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a // indirect
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||||
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||||
|
k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b
|
||||||
|
k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d
|
||||||
|
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
|
||||||
|
k8s.io/klog v0.3.0
|
||||||
|
k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7 // indirect
|
||||||
|
sigs.k8s.io/yaml v1.1.0 // indirect
|
||||||
|
)
|
||||||
123
go.sum
Normal file
123
go.sum
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||||
|
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
|
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
|
||||||
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
|
||||||
|
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||||
|
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g=
|
||||||
|
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
|
||||||
|
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
|
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be h1:AHimNtVIpiBjPUhEF5KNCkrUyqTSA5zWUl8sQ2bfGBE=
|
||||||
|
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/openshift/api v3.9.0+incompatible h1:fJ/KsefYuZAjmrr3+5U9yZIZbTOpVkDDLDLFresAeYs=
|
||||||
|
github.com/openshift/api v3.9.0+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||||
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
|
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/stakater/IngressMonitorController v1.0.62 h1:KLC79Qo8YNEcNehPSEDrZ1vEtqPux1fnNnXC4m43Lhk=
|
||||||
|
github.com/stakater/IngressMonitorController v1.0.62/go.mod h1:LXpqENu96n+xgxMr1GGSRKydCrVaszM21Y8PKTb+JK8=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a h1:Igim7XhdOpBnWPuYJ70XcNpq8q3BCACtVgNfoJxOV7g=
|
||||||
|
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190415100556-4a65cf94b679 h1:tzVWzOrXxwAwdSCMrf+mbNrZFxwS0+HLP4m2qxtfdhk=
|
||||||
|
golang.org/x/net v0.0.0-20190415100556-4a65cf94b679/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
|
||||||
|
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU=
|
||||||
|
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o=
|
||||||
|
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b h1:aBGgKJUM9Hk/3AE8WaZIApnTxG35kbuQba2w+SXqezo=
|
||||||
|
k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
|
||||||
|
k8s.io/api v0.0.0-20190415132514-c2f1300cac21 h1:XGJCFakX0XXD6V2frIsafsr96sDU1q6Gcvm2JaFQVyM=
|
||||||
|
k8s.io/api v0.0.0-20190415132514-c2f1300cac21/go.mod h1:5HMaKNcWJji8AGOBjOZxmFDwRutMItn4MrrXZcFANNo=
|
||||||
|
k8s.io/api v0.0.0-20190417212520-7b2abe144378 h1:5MbuLXn4OcNwi6vnf6OqDuMvZQQFMG5Bl97Ji6U+v/I=
|
||||||
|
k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d h1:Jmdtdt1ZnoGfWWIIik61Z7nKYgO3J+swQJtPYsP9wHA=
|
||||||
|
k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
|
||||||
|
k8s.io/apimachinery v0.0.0-20190415132420-07d458fe0356 h1:IneIG23feOS594nIIsJVRUHK50ALz/g0/Co/3iML7RI=
|
||||||
|
k8s.io/apimachinery v0.0.0-20190415132420-07d458fe0356/go.mod h1:jLjiXl596L+wVGdx8dRx6sSNnabzqnI2+nAJqqqyesQ=
|
||||||
|
k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o=
|
||||||
|
k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
|
||||||
|
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible h1:U5Bt+dab9K8qaUmXINrkXO135kA11/i5Kg1RUydgaMQ=
|
||||||
|
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
|
||||||
|
k8s.io/klog v0.0.0-20190306015804-8e90cee79f82/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
|
k8s.io/klog v0.3.0 h1:0VPpR+sizsiivjIfIAQH/rl8tan6jvWkS7lU+0di3lE=
|
||||||
|
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30 h1:TRb4wNWoBVrH9plmkp2q86FIDppkbrEXdXlxU3a3BMI=
|
||||||
|
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
|
||||||
|
k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7 h1:8r+l4bNWjRlsFYlQJnKJ2p7s1YQPj4XyXiJVqDHRx7c=
|
||||||
|
k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
|
||||||
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
24
hack/test/example-deployment.yaml
Normal file
24
hack/test/example-deployment.yaml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
labels:
|
||||||
|
app: example
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: example
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: example
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: httpecho
|
||||||
|
image: hashicorp/http-echo
|
||||||
|
args:
|
||||||
|
- "-listen=:8080"
|
||||||
|
- "-text=hello world"
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
13
hack/test/example-ingress.yaml
Normal file
13
hack/test/example-ingress.yaml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: hello-world.xyz
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /*
|
||||||
|
backend:
|
||||||
|
serviceName: example
|
||||||
|
servicePort: 8080
|
||||||
12
hack/test/example-service.yaml
Normal file
12
hack/test/example-service.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
kind: Service
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: example
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: example
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
97
internal/controller/action.go
Normal file
97
internal/controller/action.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/api/extensions/v1beta1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *CaddyController) onResourceAdded(obj interface{}) {
|
||||||
|
c.syncQueue.Add(ResourceAddedAction{
|
||||||
|
resource: obj,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CaddyController) onResourceUpdated(old interface{}, new interface{}) {
|
||||||
|
c.syncQueue.Add(ResourceUpdatedAction{
|
||||||
|
resource: new,
|
||||||
|
oldResource: old,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CaddyController) onResourceDeleted(obj interface{}) {
|
||||||
|
c.syncQueue.Add(ResourceDeletedAction{
|
||||||
|
resource: obj,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CaddyController) onSyncStatus(obj interface{}) {
|
||||||
|
c.syncQueue.Add(SyncStatusAction{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action is an interface for ingress actions
|
||||||
|
type Action interface {
|
||||||
|
handle(c *CaddyController) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceAddedAction provides an implementation of the action interface
|
||||||
|
type ResourceAddedAction struct {
|
||||||
|
resource interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceUpdatedAction provides an implementation of the action interface
|
||||||
|
type ResourceUpdatedAction struct {
|
||||||
|
resource interface{}
|
||||||
|
oldResource interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceDeletedAction provides an implementation of the action interface
|
||||||
|
type ResourceDeletedAction struct {
|
||||||
|
resource interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ResourceAddedAction) handle(c *CaddyController) error {
|
||||||
|
// configure caddy to handle this resource
|
||||||
|
ing, ok := r.resource.(*v1beta1.Ingress)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("ResourceAddedAction: incoming resource is not of type ingress")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Parse ingress resource and convert to obj to configure caddy with
|
||||||
|
// 2. Get current caddy config for rollback purposes
|
||||||
|
// 3. Update internal caddy config
|
||||||
|
// 4. Get ingress controller publish address
|
||||||
|
// 5. call syncIngress for this specific resource
|
||||||
|
// 6. Add this ingress to resource store
|
||||||
|
|
||||||
|
c.resourceStore.AddIngress(ing)
|
||||||
|
|
||||||
|
// ~~~~
|
||||||
|
// when updating caddy config the ingress controller should bypass kube-proxy and get the ip address of
|
||||||
|
// the pod that the deployment we are proxying to is running on so that we can proxy to that ip address port.
|
||||||
|
// this is good for session affinity and increases performance (since we don't have to hit dns).
|
||||||
|
|
||||||
|
// example getting an ingress
|
||||||
|
// ingClient := c.kubeClient.ExtensionsV1beta1().Ingresses(c.namespace) // get a client to update the ingress
|
||||||
|
// ingClient.UpdateStatus(ing) // pass an ingress with the status.address field updated
|
||||||
|
// ~~~
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ResourceUpdatedAction) handle(c *CaddyController) error {
|
||||||
|
// find the caddy config related to the oldResource and update it
|
||||||
|
|
||||||
|
fmt.Printf("\nUpdated resource:\n +%v\n\nOld resource: \n %+v\n", r.resource, r.oldResource)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ResourceDeletedAction) handle(c *CaddyController) error {
|
||||||
|
// delete all resources from caddy config that are associated with this resource
|
||||||
|
// reload caddy config
|
||||||
|
|
||||||
|
fmt.Printf("\nDeleted resource:\n +%v\n", r.resource)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
160
internal/controller/controller.go
Normal file
160
internal/controller/controller.go
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"bitbucket.org/lightcodelabs/ingress/internal/store"
|
||||||
|
"k8s.io/api/extensions/v1beta1"
|
||||||
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
|
run "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"k8s.io/client-go/tools/cache"
|
||||||
|
"k8s.io/client-go/util/workqueue"
|
||||||
|
"k8s.io/klog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResourceMap are resources from where changes are going to be detected
|
||||||
|
var ResourceMap = map[string]run.Object{
|
||||||
|
"ingresses": &v1beta1.Ingress{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// how often we should attempt to keep ingress resource's source address in sync
|
||||||
|
const syncInterval = time.Second * 60
|
||||||
|
|
||||||
|
// CaddyController represents an caddy ingress controller.
|
||||||
|
type CaddyController struct {
|
||||||
|
resourceStore *store.Store
|
||||||
|
kubeClient *kubernetes.Clientset
|
||||||
|
namespace string
|
||||||
|
indexer cache.Indexer
|
||||||
|
syncQueue workqueue.RateLimitingInterface
|
||||||
|
statusQueue workqueue.RateLimitingInterface // statusQueue performs ingress status updates every 60 seconds but inserts the work into the sync queue
|
||||||
|
informer cache.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCaddyController returns an instance of the caddy ingress controller.
|
||||||
|
func NewCaddyController(namespace string, kubeClient *kubernetes.Clientset, resource string, restClient rest.Interface) *CaddyController {
|
||||||
|
controller := &CaddyController{
|
||||||
|
kubeClient: kubeClient,
|
||||||
|
namespace: namespace,
|
||||||
|
syncQueue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()),
|
||||||
|
statusQueue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()),
|
||||||
|
}
|
||||||
|
|
||||||
|
ingressListWatcher := cache.NewListWatchFromClient(restClient, resource, namespace, fields.Everything())
|
||||||
|
indexer, informer := cache.NewIndexerInformer(ingressListWatcher, ResourceMap[resource], 0, cache.ResourceEventHandlerFuncs{
|
||||||
|
AddFunc: controller.onResourceAdded,
|
||||||
|
UpdateFunc: controller.onResourceUpdated,
|
||||||
|
DeleteFunc: controller.onResourceDeleted,
|
||||||
|
}, cache.Indexers{})
|
||||||
|
|
||||||
|
controller.indexer = indexer
|
||||||
|
controller.informer = informer
|
||||||
|
controller.resourceStore = store.NewStore(controller.kubeClient)
|
||||||
|
|
||||||
|
// =======
|
||||||
|
// TODO :- get info of the current pod, we'll need the ip address so we can forward requests to this ingress
|
||||||
|
// controller
|
||||||
|
|
||||||
|
// podInfo, err := k8s.GetPodDetails(kubeClient)
|
||||||
|
// if err != nil {
|
||||||
|
// klog.Fatalf("Unexpected error obtaining pod information: %v", err)
|
||||||
|
// }
|
||||||
|
// =======
|
||||||
|
|
||||||
|
// TODO :- attempt to do initial sync with ingresses here
|
||||||
|
|
||||||
|
return controller
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown stops the caddy controller.
|
||||||
|
func (c *CaddyController) Shutdown() error {
|
||||||
|
// TODO :- implement a graceful shutdown for the ingress controller and caddy server
|
||||||
|
|
||||||
|
// shutdown statusQueue
|
||||||
|
|
||||||
|
// shutdown syncQueue
|
||||||
|
|
||||||
|
// shutdownCaddy
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleErrs reports errors received from queue actions.
|
||||||
|
func (c *CaddyController) handleErr(err error, action interface{}) {
|
||||||
|
klog.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run method starts the ingress controller.
|
||||||
|
func (c *CaddyController) Run(stopCh chan struct{}) {
|
||||||
|
klog.Info("starting caddy ingress controller")
|
||||||
|
|
||||||
|
// TODO :- start an instance of caddy server
|
||||||
|
|
||||||
|
defer runtime.HandleCrash()
|
||||||
|
defer c.syncQueue.ShutDown()
|
||||||
|
|
||||||
|
// start the ingress informer where we listen to new / updated ingress resources
|
||||||
|
go c.informer.Run(stopCh)
|
||||||
|
|
||||||
|
// wait for all involved caches to be synced, before processing items from the queue is started
|
||||||
|
if !cache.WaitForCacheSync(stopCh, c.informer.HasSynced) {
|
||||||
|
runtime.HandleError(fmt.Errorf("Timed out waiting for caches to sync"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// start processing events for syncing ingress resources
|
||||||
|
go wait.Until(c.runWorker, time.Second, stopCh)
|
||||||
|
|
||||||
|
// start ingress status syncher
|
||||||
|
go wait.Until(c.dispatchSync, syncInterval, stopCh)
|
||||||
|
|
||||||
|
<-stopCh
|
||||||
|
klog.Info("stopping ingress controller")
|
||||||
|
|
||||||
|
exitCode := 0
|
||||||
|
err := c.Shutdown()
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("could not shutdown ingress controller properly")
|
||||||
|
exitCode = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(exitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO :- copy this for the status updater for ingress controllers
|
||||||
|
// every 60 seconds attempt to update the statusIP for ingresses
|
||||||
|
// add into the syncqueue
|
||||||
|
|
||||||
|
// process items in the event queue
|
||||||
|
func (c *CaddyController) runWorker() {
|
||||||
|
for c.processNextItem() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is an ingress item in the event queue process it
|
||||||
|
func (c *CaddyController) processNextItem() bool {
|
||||||
|
// Wait until there is a new item in the working queue
|
||||||
|
action, quit := c.syncQueue.Get()
|
||||||
|
if quit {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell the queue that we are done with processing this key. This unblocks the key for other workers
|
||||||
|
// This allows safe parallel processing because two ingresses with the same key are never processed in
|
||||||
|
// parallel.
|
||||||
|
defer c.syncQueue.Done(action)
|
||||||
|
|
||||||
|
// Invoke the method containing the business logic
|
||||||
|
err := action.(Action).handle(c)
|
||||||
|
if err != nil {
|
||||||
|
c.handleErr(err, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
28
internal/controller/status.go
Normal file
28
internal/controller/status.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/api/extensions/v1beta1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// dispatchSync is run every syncInterval duration to sync ingress source address fields.
|
||||||
|
func (c *CaddyController) dispatchSync() {
|
||||||
|
c.syncQueue.Add(SyncStatusAction{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncStatusAction provides an implementation of the action interface
|
||||||
|
type SyncStatusAction struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r SyncStatusAction) handle(c *CaddyController) error {
|
||||||
|
c.syncStatus(c.resourceStore.Ingresses)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// syncStatus ensures that the ingress source address points to this ingress controller's IP address.
|
||||||
|
func (c *CaddyController) syncStatus(ings []*v1beta1.Ingress) {
|
||||||
|
// TODO :- update source address to ingress controller published address
|
||||||
|
|
||||||
|
fmt.Println("Handle Synching Ingress Source Address")
|
||||||
|
}
|
||||||
3
internal/ingress/ingress.go
Normal file
3
internal/ingress/ingress.go
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package ingress
|
||||||
|
|
||||||
|
// handle getting ingress information here
|
||||||
49
internal/store/store.go
Normal file
49
internal/store/store.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package store
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/api/extensions/v1beta1"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Store represents a collection of ingresses and secrets that we are monitoring.
|
||||||
|
type Store struct {
|
||||||
|
Ingresses []*v1beta1.Ingress
|
||||||
|
Secrets []interface{} // TODO :- should we store the secrets in the ingress object?
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStore returns a new store that keeps track of ingresses and secrets. It will attempt to get
|
||||||
|
// all current ingresses before returning.
|
||||||
|
func NewStore(kubeClient *kubernetes.Clientset) *Store {
|
||||||
|
ingresses, err := kubeClient.ExtensionsV1beta1().Ingresses("").List(v1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
klog.Errorf("could not get existing ingresses in cluster")
|
||||||
|
return &Store{}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &Store{
|
||||||
|
Ingresses: make([]*v1beta1.Ingress, len(ingresses.Items)-1),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, i := range ingresses.Items {
|
||||||
|
s.Ingresses = append(s.Ingresses, &i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddIngress adds an ingress to the store
|
||||||
|
func (s *Store) AddIngress(ing *v1beta1.Ingress) {
|
||||||
|
isUniq := true
|
||||||
|
|
||||||
|
for _, i := range s.Ingresses {
|
||||||
|
if i.GetUID() == ing.GetUID() {
|
||||||
|
isUniq = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isUniq {
|
||||||
|
s.Ingresses = append(s.Ingresses, ing)
|
||||||
|
}
|
||||||
|
}
|
||||||
27
kubernetes/generated/clusterrole.yaml
Normal file
27
kubernetes/generated/clusterrole.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: caddyingresscontroller-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses
|
||||||
|
- routes
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- watch
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- watch
|
||||||
12
kubernetes/generated/clusterrolebinding.yaml
Normal file
12
kubernetes/generated/clusterrolebinding.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: caddyingresscontroller-role-binding
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: caddyingresscontroller-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: caddyingresscontroller
|
||||||
|
namespace: default
|
||||||
34
kubernetes/generated/deployment.yaml
Normal file
34
kubernetes/generated/deployment.yaml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: caddyingresscontroller
|
||||||
|
labels:
|
||||||
|
app: caddyIngressController
|
||||||
|
chart: "caddyingresscontroller-v0.1.0"
|
||||||
|
release: "release-name"
|
||||||
|
heritage: "Tiller"
|
||||||
|
version: v0.1.0
|
||||||
|
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: caddyIngressController
|
||||||
|
release: "release-name"
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: caddyIngressController
|
||||||
|
chart: "caddyingresscontroller-v0.1.0"
|
||||||
|
release: "release-name"
|
||||||
|
heritage: "Tiller"
|
||||||
|
version: v0.1.0
|
||||||
|
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
image: "caddy/ingresscontroller"
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
name: caddyingresscontroller
|
||||||
|
serviceAccountName: caddyingresscontroller
|
||||||
10
kubernetes/generated/serviceaccount.yaml
Normal file
10
kubernetes/generated/serviceaccount.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: caddyingresscontroller
|
||||||
|
labels:
|
||||||
|
app: caddyIngressController
|
||||||
|
chart: "caddyingresscontroller-v0.1.0"
|
||||||
|
release: "release-name"
|
||||||
|
heritage: "Tiller"
|
||||||
|
version: v0.1.0
|
||||||
4
kubernetes/helm/caddyingresscontroller/Chart.yaml
Normal file
4
kubernetes/helm/caddyingresscontroller/Chart.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
description: A helm chart for the Caddy Kubernetes ingress controller
|
||||||
|
name: caddyingresscontroller
|
||||||
|
version: v0.1.0
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
{{- if and ( .Values.caddyingresscontroller.rbac.create ) (eq .Values.caddyingresscontroller.watchNamespace "") }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.name }}-role
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses
|
||||||
|
- routes
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- watch
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- watch
|
||||||
|
{{- end }}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
{{- if and ( .Values.caddyingresscontroller.rbac.create ) (eq .Values.caddyingresscontroller.watchNamespace "") }}
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.name }}-role-binding
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: {{ .Values.name }}-role
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ .Values.serviceAccountName }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.name }}
|
||||||
|
labels:
|
||||||
|
app: {{ .Values.name }}
|
||||||
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
|
release: {{ .Release.Name | quote }}
|
||||||
|
heritage: {{ .Release.Service | quote }}
|
||||||
|
{{- if .Values.caddyingresscontroller.deployment.labels }}
|
||||||
|
{{ toYaml .Values.caddyingresscontroller.deployment.labels | indent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
revisionHistoryLimit: 2
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ .Values.name }}
|
||||||
|
release: {{ .Release.Name | quote }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: {{ .Values.name }}
|
||||||
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
|
release: {{ .Release.Name | quote }}
|
||||||
|
heritage: {{ .Release.Service | quote }}
|
||||||
|
{{- if .Values.caddyingresscontroller.deployment.labels }}
|
||||||
|
{{ toYaml .Values.caddyingresscontroller.deployment.labels | indent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- env:
|
||||||
|
{{- if .Values.caddyingresscontroller.watchNamespace }}
|
||||||
|
- name: KUBERNETES_NAMESPACE
|
||||||
|
value: {{ .Values.caddyingresscontroller.watchNamespace | quote }}
|
||||||
|
{{- end }}
|
||||||
|
image: "{{ .Values.caddyingresscontroller.image.name }}:{{ .Values.caddyingresscontroller.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.caddyingresscontroller.image.pullPolicy }}
|
||||||
|
name: {{ .Values.name }}
|
||||||
|
serviceAccountName: {{ .Values.serviceAccountName }}
|
||||||
30
kubernetes/helm/caddyingresscontroller/templates/role.yaml
Normal file
30
kubernetes/helm/caddyingresscontroller/templates/role.yaml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{{- if and ( .Values.caddyingresscontroller.rbac.create ) (.Values.caddyingresscontroller.watchNamespace) }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.name }}-role
|
||||||
|
namespace: {{ .Values.caddyingresscontroller.watchNamespace | quote }}
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
- "extensions"
|
||||||
|
resources:
|
||||||
|
- ingresses
|
||||||
|
- routes
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- update
|
||||||
|
- patch
|
||||||
|
- watch
|
||||||
|
- delete
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- services
|
||||||
|
- pods
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- get
|
||||||
|
- watch
|
||||||
|
{{- end }}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
{{- if and ( .Values.caddyingresscontroller.rbac.create ) (.Values.caddyingresscontroller.watchNamespace) }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.name }}-role-binding
|
||||||
|
namespace: {{ .Values.caddyingresscontroller.watchNamespace | quote }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ .Values.name }}-role
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ .Values.serviceAccountName }}
|
||||||
|
namespace: {{ .Release.Namespace | quote }}
|
||||||
|
{{- end }}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
{{- if .Values.caddyingresscontroller.serviceAccount.create }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: {{ .Values.name }}
|
||||||
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
|
release: {{ .Release.Name | quote }}
|
||||||
|
heritage: {{ .Release.Service | quote }}
|
||||||
|
{{- if .Values.caddyingresscontroller.serviceAccount.labels }}
|
||||||
|
{{ toYaml .Values.caddyingresscontroller.serviceAccount.labels | indent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.caddyingresscontroller.matchLabels }}
|
||||||
|
{{ toYaml .Values.caddyingresscontroller.matchLabels | indent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
name: {{ .Values.serviceAccountName }}
|
||||||
|
{{- end }}
|
||||||
34
kubernetes/helm/caddyingresscontroller/values.yaml
Normal file
34
kubernetes/helm/caddyingresscontroller/values.yaml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Default values for caddyingresscontroller.
|
||||||
|
# This is a YAML-formatted file.
|
||||||
|
# Declare variables to be passed into your templates.
|
||||||
|
|
||||||
|
kubernetes:
|
||||||
|
host: https://kubernetes.default
|
||||||
|
|
||||||
|
caddyingresscontroller:
|
||||||
|
tolerations: {}
|
||||||
|
watchNamespace: ""
|
||||||
|
deployment:
|
||||||
|
labels:
|
||||||
|
version: "v0.1.0"
|
||||||
|
config:
|
||||||
|
labels:
|
||||||
|
version: "v0.1.0"
|
||||||
|
rbac:
|
||||||
|
create: true
|
||||||
|
# Service account config for the agent pods
|
||||||
|
serviceAccount:
|
||||||
|
# Specifies whether a ServiceAccount should be created
|
||||||
|
create: true
|
||||||
|
labels:
|
||||||
|
version: "v0.1.0"
|
||||||
|
# The name of the ServiceAccount to use.
|
||||||
|
# If not set and create is true, a name is generated using the fullname template
|
||||||
|
name: caddyIngressController
|
||||||
|
image:
|
||||||
|
name: caddy/ingresscontroller
|
||||||
|
tag: "v0.1.0"
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
name: "caddyingresscontroller"
|
||||||
|
serviceAccountName: "caddyingresscontroller"
|
||||||
12
skaffold.yaml
Normal file
12
skaffold.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: skaffold/v1beta8
|
||||||
|
kind: Config
|
||||||
|
build:
|
||||||
|
artifacts:
|
||||||
|
- image: caddy/ingresscontroller
|
||||||
|
deploy:
|
||||||
|
kubectl:
|
||||||
|
manifests:
|
||||||
|
- kubernetes/generated/clusterrole.yaml
|
||||||
|
- kubernetes/generated/clusterrolebinding.yaml
|
||||||
|
- kubernetes/generated/deployment.yaml
|
||||||
|
- kubernetes/generated/serviceaccount.yaml
|
||||||
Loading…
x
Reference in New Issue
Block a user