From eeb633ce01fda9cbb44b8b6863900b0e275e6a3b Mon Sep 17 00:00:00 2001 From: dev Date: Tue, 23 Apr 2019 17:45:18 -0400 Subject: [PATCH] integrate with minikube and caddy server --- Dockerfile | 1 + Gopkg.lock | 637 ++++++++++++++++++ Gopkg.toml | 46 ++ go.mod | 31 - go.sum | 123 ---- hack/test/example-ingress.yaml | 4 +- internal/caddy/config.go | 90 +++ internal/caddy/import.go | 20 + internal/controller/action.go | 29 +- internal/controller/controller.go | 73 +- internal/controller/ingress.go | 98 +++ internal/controller/status.go | 39 +- internal/ingress/ingress.go | 3 - internal/pod/pod.go | 99 +++ internal/store/store.go | 9 +- kubernetes/generated/clusterrole.yaml | 3 + kubernetes/generated/deployment.yaml | 31 +- .../templates/deployment.yaml | 20 +- skaffold.yaml | 3 + 19 files changed, 1148 insertions(+), 211 deletions(-) create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml delete mode 100644 go.mod delete mode 100644 go.sum create mode 100644 internal/caddy/config.go create mode 100644 internal/caddy/import.go create mode 100644 internal/controller/ingress.go delete mode 100644 internal/ingress/ingress.go create mode 100644 internal/pod/pod.go diff --git a/Dockerfile b/Dockerfile index 36d686a..20c137c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,4 @@ FROM scratch COPY ./bin/ingress-controller . +EXPOSE 80 443 ENTRYPOINT ["/ingress-controller"] \ No newline at end of file diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..f94431c --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,637 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "UT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" + +[[projects]] + digest = "1:58be7025fd84632dfbb8a398f931b5bdbbecc0390e4385df4ae56775487a0f87" + name = "github.com/docker/spdystream" + packages = [ + ".", + "spdy", + ] + pruneopts = "UT" + revision = "449fdfce4d96" + +[[projects]] + digest = "1:9886f20fc7188af1fb9059c6b6b29da154f87a05986a84ab297a5b6a779f230f" + name = "github.com/gogo/protobuf" + packages = [ + "gogoproto", + "proto", + "protoc-gen-gogo/descriptor", + "sortkeys", + ] + pruneopts = "UT" + revision = "342cbe0a0415" + +[[projects]] + digest = "1:7672c206322f45b33fac1ae2cb899263533ce0adcc6481d207725560208ec84e" + name = "github.com/golang/groupcache" + packages = ["lru"] + pruneopts = "UT" + revision = "02826c3e7903" + +[[projects]] + digest = "1:239c4c7fd2159585454003d9be7207167970194216193a8a210b8d29576f19c9" + name = "github.com/golang/protobuf" + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp", + ] + pruneopts = "UT" + revision = "b5d812f8a3706043e23a9cd5babf2e5423744d30" + version = "v1.3.1" + +[[projects]] + digest = "1:3ee90c0d94da31b442dde97c99635aaafec68d0b8a3c12ee2075c6bdabeec6bb" + name = "github.com/google/gofuzz" + packages = ["."] + pruneopts = "UT" + revision = "24818f796faf" + +[[projects]] + digest = "1:75eb87381d25cc75212f52358df9c3a2719584eaa9685cd510ce28699122f39d" + name = "github.com/googleapis/gnostic" + packages = [ + "OpenAPIv2", + "compiler", + "extensions", + ] + pruneopts = "UT" + revision = "0c5108395e2d" + +[[projects]] + digest = "1:8ec8d88c248041a6df5f6574b87bc00e7e0b493881dad2e7ef47b11dc69093b5" + name = "github.com/hashicorp/golang-lru" + packages = [ + ".", + "simplelru", + ] + pruneopts = "UT" + revision = "20f1fb78b0740ba8c3cb143a61e86ba5c8669768" + version = "v0.5.0" + +[[projects]] + digest = "1:3e260afa138eab6492b531a3b3d10ab4cb70512d423faa78b8949dec76e66a21" + name = "github.com/imdario/mergo" + packages = ["."] + pruneopts = "UT" + revision = "9316a62528ac99aaecb4e47eadd6dc8aa6533d58" + version = "v0.3.5" + +[[projects]] + digest = "1:eaefc85d32c03e5f0c2b88ea2f79fce3d993e2c78316d21319575dd4ea9153ca" + name = "github.com/json-iterator/go" + packages = ["."] + pruneopts = "UT" + revision = "ab8a2e0c74be" + +[[projects]] + digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563" + name = "github.com/modern-go/concurrent" + packages = ["."] + pruneopts = "UT" + revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + version = "1.0.3" + +[[projects]] + digest = "1:c56ad36f5722eb07926c979d5e80676ee007a9e39e7808577b9d87ec92b00460" + name = "github.com/modern-go/reflect2" + packages = ["."] + pruneopts = "UT" + revision = "94122c33edd36123c84d5368cfb2b69df93a0ec8" + version = "v1.0.1" + +[[projects]] + digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b" + name = "github.com/pkg/errors" + packages = ["."] + pruneopts = "UT" + revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" + version = "v0.8.1" + +[[projects]] + digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7" + name = "github.com/spf13/pflag" + packages = ["."] + pruneopts = "UT" + revision = "583c0c0531f06d5278b7d917446061adc344b5cd" + version = "v1.0.1" + +[[projects]] + digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8" + name = "golang.org/x/crypto" + packages = ["ssh/terminal"] + pruneopts = "UT" + revision = "e84da0312774" + +[[projects]] + digest = "1:fc7b6b4384e1e849d99eab58eca4f8c0a76bad4699117d5077a9a5c3c83e289e" + name = "golang.org/x/net" + packages = [ + "context", + "http/httpguts", + "http2", + "http2/hpack", + "idna", + "internal/timeseries", + "trace", + ] + pruneopts = "UT" + revision = "65e2d4e15006" + +[[projects]] + digest = "1:9359217acc6040b4be710ce34473acef28023ad39bfafecea34ffaea7f1e1890" + name = "golang.org/x/oauth2" + packages = [ + ".", + "internal", + ] + pruneopts = "UT" + revision = "a6bd8cefa181" + +[[projects]] + branch = "master" + digest = "1:e18a5437c48ea1bd6dcd960efdd634d05ae5c2dd033d2d17f73cc20be92895ac" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows", + ] + pruneopts = "UT" + revision = "f0ce4c0180bef7e9c51babed693a6e47fdd8962f" + +[[projects]] + digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + ] + pruneopts = "UT" + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + digest = "1:d37b0ef2944431fe9e8ef35c6fffc8990d9e2ca300588df94a6890f3649ae365" + name = "golang.org/x/time" + packages = ["rate"] + pruneopts = "UT" + revision = "f51c12702a4d" + +[[projects]] + digest = "1:6eb6e3b6d9fffb62958cf7f7d88dbbe1dd6839436b0802e194c590667a40412a" + name = "google.golang.org/appengine" + packages = [ + "internal", + "internal/base", + "internal/datastore", + "internal/log", + "internal/remote_api", + "internal/urlfetch", + "urlfetch", + ] + pruneopts = "UT" + revision = "54a98f90d1c46b7731eb8fb305d2a321c30ef610" + version = "v1.5.0" + +[[projects]] + branch = "master" + digest = "1:c3076e7defee87de1236f1814beb588f40a75544c60121e6eb38b3b3721783e2" + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + pruneopts = "UT" + revision = "e7d98fc518a78c9f8b5ee77be7b0b317475d89e1" + +[[projects]] + digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" + name = "google.golang.org/grpc" + packages = [ + ".", + "balancer", + "balancer/base", + "balancer/roundrobin", + "codes", + "connectivity", + "credentials", + "encoding", + "encoding/proto", + "grpclog", + "internal", + "internal/backoff", + "internal/channelz", + "internal/grpcrand", + "keepalive", + "metadata", + "naming", + "peer", + "resolver", + "resolver/dns", + "resolver/passthrough", + "stats", + "status", + "tap", + "transport", + ] + pruneopts = "UT" + revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8" + version = "v1.13.0" + +[[projects]] + digest = "1:b699eb24813add6abe916da7d11a93ae2a4122dc9bfa103fee775cb435d3dc9b" + name = "gopkg.in/go-playground/pool.v3" + packages = ["."] + pruneopts = "UT" + revision = "e73cd3a5ded835540c5cf4778488579c5b357d68" + version = "v3.1.1" + +[[projects]] + digest = "1:ef72505cf098abdd34efeea032103377bec06abb61d8a06f002d5d296a4b1185" + name = "gopkg.in/inf.v0" + packages = ["."] + pruneopts = "UT" + revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" + version = "v0.9.0" + +[[projects]] + digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96" + name = "gopkg.in/yaml.v2" + packages = ["."] + pruneopts = "UT" + revision = "51d6538a90f86fe93ac480b35f37b2be17fef232" + version = "v2.2.2" + +[[projects]] + branch = "master" + digest = "1:08f27db4a5192ae419db7d6fb2c402c7faf3605ef3fb30c0976bdb34ee196947" + name = "k8s.io/api" + packages = [ + "admissionregistration/v1beta1", + "apps/v1", + "apps/v1beta1", + "apps/v1beta2", + "auditregistration/v1alpha1", + "authentication/v1", + "authentication/v1beta1", + "authorization/v1", + "authorization/v1beta1", + "autoscaling/v1", + "autoscaling/v2beta1", + "autoscaling/v2beta2", + "batch/v1", + "batch/v1beta1", + "batch/v2alpha1", + "certificates/v1beta1", + "coordination/v1", + "coordination/v1beta1", + "core/v1", + "events/v1beta1", + "extensions/v1beta1", + "networking/v1", + "networking/v1beta1", + "node/v1alpha1", + "node/v1beta1", + "policy/v1beta1", + "rbac/v1", + "rbac/v1alpha1", + "rbac/v1beta1", + "scheduling/v1", + "scheduling/v1alpha1", + "scheduling/v1beta1", + "settings/v1alpha1", + "storage/v1", + "storage/v1alpha1", + "storage/v1beta1", + ] + pruneopts = "UT" + revision = "c5cad27821f602a806fbc313abf36f20aec596de" + +[[projects]] + digest = "1:755eded9d4a8ce43f0d3d93ec8ea14a469a87740f4483be5021434a4b4ac209e" + name = "k8s.io/apimachinery" + packages = [ + "pkg/api/errors", + "pkg/api/meta", + "pkg/api/resource", + "pkg/apis/meta/internalversion", + "pkg/apis/meta/v1", + "pkg/apis/meta/v1/unstructured", + "pkg/apis/meta/v1beta1", + "pkg/conversion", + "pkg/conversion/queryparams", + "pkg/fields", + "pkg/labels", + "pkg/runtime", + "pkg/runtime/schema", + "pkg/runtime/serializer", + "pkg/runtime/serializer/json", + "pkg/runtime/serializer/protobuf", + "pkg/runtime/serializer/recognizer", + "pkg/runtime/serializer/streaming", + "pkg/runtime/serializer/versioning", + "pkg/selection", + "pkg/types", + "pkg/util/cache", + "pkg/util/clock", + "pkg/util/diff", + "pkg/util/errors", + "pkg/util/framer", + "pkg/util/httpstream", + "pkg/util/httpstream/spdy", + "pkg/util/intstr", + "pkg/util/json", + "pkg/util/mergepatch", + "pkg/util/naming", + "pkg/util/net", + "pkg/util/remotecommand", + "pkg/util/runtime", + "pkg/util/sets", + "pkg/util/strategicpatch", + "pkg/util/validation", + "pkg/util/validation/field", + "pkg/util/wait", + "pkg/util/yaml", + "pkg/version", + "pkg/watch", + "third_party/forked/golang/json", + "third_party/forked/golang/netutil", + "third_party/forked/golang/reflect", + ] + pruneopts = "UT" + revision = "b3683fe6b520" + +[[projects]] + branch = "master" + digest = "1:642e57dc486ef777e094364e3fe25cd6f63a5f4412f8df91c2674406ec44371e" + name = "k8s.io/client-go" + packages = [ + "discovery", + "informers", + "informers/admissionregistration", + "informers/admissionregistration/v1beta1", + "informers/apps", + "informers/apps/v1", + "informers/apps/v1beta1", + "informers/apps/v1beta2", + "informers/auditregistration", + "informers/auditregistration/v1alpha1", + "informers/autoscaling", + "informers/autoscaling/v1", + "informers/autoscaling/v2beta1", + "informers/autoscaling/v2beta2", + "informers/batch", + "informers/batch/v1", + "informers/batch/v1beta1", + "informers/batch/v2alpha1", + "informers/certificates", + "informers/certificates/v1beta1", + "informers/coordination", + "informers/coordination/v1", + "informers/coordination/v1beta1", + "informers/core", + "informers/core/v1", + "informers/events", + "informers/events/v1beta1", + "informers/extensions", + "informers/extensions/v1beta1", + "informers/internalinterfaces", + "informers/networking", + "informers/networking/v1", + "informers/networking/v1beta1", + "informers/node", + "informers/node/v1alpha1", + "informers/node/v1beta1", + "informers/policy", + "informers/policy/v1beta1", + "informers/rbac", + "informers/rbac/v1", + "informers/rbac/v1alpha1", + "informers/rbac/v1beta1", + "informers/scheduling", + "informers/scheduling/v1", + "informers/scheduling/v1alpha1", + "informers/scheduling/v1beta1", + "informers/settings", + "informers/settings/v1alpha1", + "informers/storage", + "informers/storage/v1", + "informers/storage/v1alpha1", + "informers/storage/v1beta1", + "kubernetes", + "kubernetes/scheme", + "kubernetes/typed/admissionregistration/v1beta1", + "kubernetes/typed/apps/v1", + "kubernetes/typed/apps/v1beta1", + "kubernetes/typed/apps/v1beta2", + "kubernetes/typed/auditregistration/v1alpha1", + "kubernetes/typed/authentication/v1", + "kubernetes/typed/authentication/v1beta1", + "kubernetes/typed/authorization/v1", + "kubernetes/typed/authorization/v1beta1", + "kubernetes/typed/autoscaling/v1", + "kubernetes/typed/autoscaling/v2beta1", + "kubernetes/typed/autoscaling/v2beta2", + "kubernetes/typed/batch/v1", + "kubernetes/typed/batch/v1beta1", + "kubernetes/typed/batch/v2alpha1", + "kubernetes/typed/certificates/v1beta1", + "kubernetes/typed/coordination/v1", + "kubernetes/typed/coordination/v1beta1", + "kubernetes/typed/core/v1", + "kubernetes/typed/events/v1beta1", + "kubernetes/typed/extensions/v1beta1", + "kubernetes/typed/networking/v1", + "kubernetes/typed/networking/v1beta1", + "kubernetes/typed/node/v1alpha1", + "kubernetes/typed/node/v1beta1", + "kubernetes/typed/policy/v1beta1", + "kubernetes/typed/rbac/v1", + "kubernetes/typed/rbac/v1alpha1", + "kubernetes/typed/rbac/v1beta1", + "kubernetes/typed/scheduling/v1", + "kubernetes/typed/scheduling/v1alpha1", + "kubernetes/typed/scheduling/v1beta1", + "kubernetes/typed/settings/v1alpha1", + "kubernetes/typed/storage/v1", + "kubernetes/typed/storage/v1alpha1", + "kubernetes/typed/storage/v1beta1", + "listers/admissionregistration/v1beta1", + "listers/apps/v1", + "listers/apps/v1beta1", + "listers/apps/v1beta2", + "listers/auditregistration/v1alpha1", + "listers/autoscaling/v1", + "listers/autoscaling/v2beta1", + "listers/autoscaling/v2beta2", + "listers/batch/v1", + "listers/batch/v1beta1", + "listers/batch/v2alpha1", + "listers/certificates/v1beta1", + "listers/coordination/v1", + "listers/coordination/v1beta1", + "listers/core/v1", + "listers/events/v1beta1", + "listers/extensions/v1beta1", + "listers/networking/v1", + "listers/networking/v1beta1", + "listers/node/v1alpha1", + "listers/node/v1beta1", + "listers/policy/v1beta1", + "listers/rbac/v1", + "listers/rbac/v1alpha1", + "listers/rbac/v1beta1", + "listers/scheduling/v1", + "listers/scheduling/v1alpha1", + "listers/scheduling/v1beta1", + "listers/settings/v1alpha1", + "listers/storage/v1", + "listers/storage/v1alpha1", + "listers/storage/v1beta1", + "pkg/apis/clientauthentication", + "pkg/apis/clientauthentication/v1alpha1", + "pkg/apis/clientauthentication/v1beta1", + "pkg/version", + "plugin/pkg/client/auth/exec", + "rest", + "rest/watch", + "tools/auth", + "tools/cache", + "tools/clientcmd", + "tools/clientcmd/api", + "tools/clientcmd/api/latest", + "tools/clientcmd/api/v1", + "tools/metrics", + "tools/pager", + "tools/record", + "tools/record/util", + "tools/reference", + "tools/remotecommand", + "transport", + "transport/spdy", + "util/cert", + "util/connrotation", + "util/exec", + "util/flowcontrol", + "util/homedir", + "util/keyutil", + "util/retry", + "util/workqueue", + ] + pruneopts = "UT" + revision = "1d2e9628a1ee6507042cfabffbe1212923cbc8d4" + +[[projects]] + branch = "master" + digest = "1:71268145ab882411833bd0546fa0c9b98d34ad83d173a3a0c35c989b5d53afe5" + name = "k8s.io/cloud-provider" + packages = ["."] + pruneopts = "UT" + revision = "029ecc113e6d819f75bde3705b0ff3fafb52d397" + +[[projects]] + digest = "1:c696379ad201c1e86591785579e16bf6cf886c362e9a7534e8eb0d1028b20582" + name = "k8s.io/klog" + packages = ["."] + pruneopts = "UT" + revision = "e531227889390a39d9533dde61f590fe9f4b0035" + version = "v0.3.0" + +[[projects]] + digest = "1:03a96603922fc1f6895ae083e1e16d943b55ef0656b56965351bd87e7d90485f" + name = "k8s.io/kube-openapi" + packages = ["pkg/util/proto"] + pruneopts = "UT" + revision = "b3a7cee44a30" + +[[projects]] + digest = "1:a86c5cf93e7fc06975cbcd13be409c044c9d57c46b44ebc340b93a8699cfc88c" + name = "k8s.io/kubernetes" + packages = [ + "pkg/api/legacyscheme", + "pkg/kubelet/apis/cri/runtime/v1alpha2", + "pkg/kubelet/container", + "pkg/kubelet/util/format", + "pkg/kubelet/util/sliceutils", + "pkg/util/hash", + "pkg/util/mount", + "pkg/volume", + "pkg/volume/util/fs", + "pkg/volume/util/recyclerclient", + "pkg/volume/util/subpath", + "third_party/forked/golang/expansion", + ] + pruneopts = "UT" + revision = "b7394102d6ef778017f2ca4046abbaa23b88c290" + version = "v1.14.1" + +[[projects]] + digest = "1:60028ab0f1ac0a17d6f193b14dc33a9282e48a4ea9583f86db98fd8f5ca0dfb8" + name = "k8s.io/utils" + packages = [ + "buffer", + "exec", + "integer", + "io", + "keymutex", + "nsenter", + "path", + "trace", + ] + pruneopts = "UT" + revision = "c2654d5206da" + +[[projects]] + digest = "1:7719608fe0b52a4ece56c2dde37bedd95b938677d1ab0f84b8a7852e4c59f849" + name = "sigs.k8s.io/yaml" + packages = ["."] + pruneopts = "UT" + revision = "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" + version = "v1.1.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/pkg/errors", + "gopkg.in/go-playground/pool.v3", + "k8s.io/api/core/v1", + "k8s.io/api/extensions/v1beta1", + "k8s.io/apimachinery/pkg/apis/meta/v1", + "k8s.io/apimachinery/pkg/fields", + "k8s.io/apimachinery/pkg/labels", + "k8s.io/apimachinery/pkg/runtime", + "k8s.io/apimachinery/pkg/util/runtime", + "k8s.io/apimachinery/pkg/util/wait", + "k8s.io/apimachinery/pkg/version", + "k8s.io/client-go/kubernetes", + "k8s.io/client-go/rest", + "k8s.io/client-go/tools/cache", + "k8s.io/client-go/tools/clientcmd", + "k8s.io/client-go/util/workqueue", + "k8s.io/klog", + "k8s.io/kubernetes/pkg/kubelet/util/sliceutils", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..3855d80 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,46 @@ +# Gopkg.toml example +# +# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + branch = "master" + name = "k8s.io/api" + +[[constraint]] + branch = "master" + name = "k8s.io/client-go" + +[[constraint]] + name = "k8s.io/klog" + version = "0.3.0" + +[[constraint]] + name = "k8s.io/kubernetes" + version = "1.14.1" + +[prune] + go-tests = true + unused-packages = true diff --git a/go.mod b/go.mod deleted file mode 100644 index 635cef5..0000000 --- a/go.mod +++ /dev/null @@ -1,31 +0,0 @@ -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 -) diff --git a/go.sum b/go.sum deleted file mode 100644 index b5b00e2..0000000 --- a/go.sum +++ /dev/null @@ -1,123 +0,0 @@ -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= diff --git a/hack/test/example-ingress.yaml b/hack/test/example-ingress.yaml index b8d82b3..cfe1f28 100644 --- a/hack/test/example-ingress.yaml +++ b/hack/test/example-ingress.yaml @@ -7,7 +7,7 @@ spec: - host: hello-world.xyz http: paths: - - path: /* + - path: /hello backend: serviceName: example - servicePort: 8080 \ No newline at end of file + servicePort: 8080 diff --git a/internal/caddy/config.go b/internal/caddy/config.go new file mode 100644 index 0000000..c83ae93 --- /dev/null +++ b/internal/caddy/config.go @@ -0,0 +1,90 @@ +package caddy + +import ( + "encoding/json" + + "bitbucket.org/lightcodelabs/caddy2" +) + +type serverRoute struct { + Matchers map[string]json.RawMessage `json:"match"` + Apply []map[string]string `json:"apply"` + Respond proxyConfig `json:"respond"` + Exclusive bool `json:"exclusive"` +} + +type routeList []serverRoute + +type proxyConfig struct { + Module string `json:"_module"` + LoadBalanceType string `json:"load_balance_type"` + Upstreams []upstreamConfig +} + +type upstreamConfig struct { + Host string `json:"host"` +} + +type httpServerConfig struct { + Listen []string `json:"listen"` + ReadTimeout caddy2.Duration `json:"read_timeout"` + ReadHeaderTimeout caddy2.Duration `json:"read_header_timeout"` + HiddenFiles []string `json:"hidden_files"` // TODO:... experimenting with shared/common state + Routes routeList `json:"routes"` + Errors httpErrorConfig `json:"errors"` +} + +type httpErrorConfig struct { + Routes routeList `json:"routes"` +} + +type serverConfig struct { + Server httpServerConfig `json:"ingress_server"` +} + +type servers struct { + Servers serverConfig `json:"servers"` +} + +type httpServer struct { + HTTP servers `json:"http"` +} + +// Config represents a caddy2 config file. +type Config struct { + Modules httpServer `json:"modules"` +} + +// NewConfig returns a plain slate caddy2 config file. +func NewConfig() *Config { + return &Config{ + Modules: httpServer{ + HTTP: servers{ + Servers: serverConfig{ + Server: httpServerConfig{ + Listen: []string{":80", ":443"}, + Routes: routeList{ + serverRoute{ + Apply: []map[string]string{ + map[string]string{ + "_module": "log", + "file": "access.log", + }, + }, + Respond: proxyConfig{ + Module: "reverse_proxy", + LoadBalanceType: "random", + Upstreams: []upstreamConfig{ + upstreamConfig{ + Host: "http://example", + }, + }, + }, + }, + }, + }, + }, + }, + }, + } +} diff --git a/internal/caddy/import.go b/internal/caddy/import.go new file mode 100644 index 0000000..73abd79 --- /dev/null +++ b/internal/caddy/import.go @@ -0,0 +1,20 @@ +package caddy + +import ( + "k8s.io/api/extensions/v1beta1" +) + +// AddIngressConfig attempts to configure caddy2 for a new ingress resource. +func AddIngressConfig(c *Config, ing *v1beta1.Ingress) (*Config, error) { + return nil, nil +} + +// UpdateIngressConfig attempts to update caddy2 config for an ingress resource that has already been configured. +func UpdateIngressConfig(c *Config, ing *v1beta1.Ingress) (*Config, error) { + return nil, nil +} + +// DeleteIngressConfig attempts to update caddy2 config to remove an ingress resource. +func DeleteIngressConfig(c *Config, ing *v1beta1.Ingress) (*Config, error) { + return nil, nil +} diff --git a/internal/controller/action.go b/internal/controller/action.go index a4224f1..5bcb55b 100644 --- a/internal/controller/action.go +++ b/internal/controller/action.go @@ -2,16 +2,20 @@ package controller import ( "fmt" + "io/ioutil" + "bitbucket.org/lightcodelabs/ingress/internal/caddy" "k8s.io/api/extensions/v1beta1" ) +// onResourceAdded runs when an ingress resource is added to the cluster. func (c *CaddyController) onResourceAdded(obj interface{}) { c.syncQueue.Add(ResourceAddedAction{ resource: obj, }) } +// onResourceUpdated is run when an ingress resource is updated in the cluster. func (c *CaddyController) onResourceUpdated(old interface{}, new interface{}) { c.syncQueue.Add(ResourceUpdatedAction{ resource: new, @@ -19,12 +23,14 @@ func (c *CaddyController) onResourceUpdated(old interface{}, new interface{}) { }) } +// onResourceDeleted is run when an ingress resource is deleted from the cluster. func (c *CaddyController) onResourceDeleted(obj interface{}) { c.syncQueue.Add(ResourceDeletedAction{ resource: obj, }) } +// onSyncStatus is run every sync interval to update the source address on ingresses. func (c *CaddyController) onSyncStatus(obj interface{}) { c.syncQueue.Add(SyncStatusAction{}) } @@ -57,12 +63,23 @@ func (r ResourceAddedAction) handle(c *CaddyController) error { 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 + // get current caddy config for rollback purposes + oldConfig := *c.resourceStore.CaddyConfig + fmt.Fprint(ioutil.Discard, oldConfig) + + // update internal caddy config with new ingress info + newConfig, err := caddy.AddIngressConfig(c.resourceStore.CaddyConfig, ing) + if err != nil { + return err + } + + // TODO :- reload caddy2 config with newConfig + fmt.Fprint(ioutil.Discard, newConfig) + + // TODO :- if err rollback to old config + + // ensure that ingress source is updated to point to this ingress controller's ip + c.syncStatus([]*v1beta1.Ingress{ing}) c.resourceStore.AddIngress(ing) diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 1e0680b..efc4de8 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -1,11 +1,17 @@ package controller import ( + "bytes" + "encoding/json" "fmt" + "log" "os" "time" + "bitbucket.org/lightcodelabs/caddy2" + "bitbucket.org/lightcodelabs/ingress/internal/pod" "bitbucket.org/lightcodelabs/ingress/internal/store" + apiv1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/fields" run "k8s.io/apimachinery/pkg/runtime" @@ -16,6 +22,11 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" "k8s.io/klog" + + // load required caddy plugins + _ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp/caddylog" + _ "bitbucket.org/lightcodelabs/caddy2/modules/caddyhttp/staticfiles" + _ "bitbucket.org/lightcodelabs/proxy" ) // ResourceMap are resources from where changes are going to be detected @@ -23,8 +34,10 @@ 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 +const ( + // how often we should attempt to keep ingress resource's source address in sync + syncInterval = time.Second * 10 +) // CaddyController represents an caddy ingress controller. type CaddyController struct { @@ -35,6 +48,7 @@ type CaddyController struct { 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 + podInfo *pod.Info } // NewCaddyController returns an instance of the caddy ingress controller. @@ -57,30 +71,28 @@ func NewCaddyController(namespace string, kubeClient *kubernetes.Clientset, reso 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 := pod.GetPodDetails(kubeClient) + if err != nil { + klog.Fatalf("Unexpected error obtaining pod information: %v", err) + } + controller.podInfo = podInfo - // 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 + // attempt to do initial sync with ingresses + controller.syncQueue.Add(SyncStatusAction{}) return controller } // Shutdown stops the caddy controller. func (c *CaddyController) Shutdown() error { - // TODO :- implement a graceful shutdown for the ingress controller and caddy server + // remove this ingress controller's ip from ingress resources. + c.updateIngStatuses([]apiv1.LoadBalancerIngress{apiv1.LoadBalancerIngress{}}, c.resourceStore.Ingresses) - // shutdown statusQueue - - // shutdown syncQueue - - // shutdownCaddy + // shutdownCaddy server gracefully + // err := caddy2.StopAdmin() + // if err != nil { + // return err + // } return nil } @@ -92,12 +104,20 @@ func (c *CaddyController) handleErr(err error, action interface{}) { // Run method starts the ingress controller. func (c *CaddyController) Run(stopCh chan struct{}) { - klog.Info("starting caddy ingress controller") + j, err := json.Marshal(c.resourceStore.CaddyConfig) + if err != nil { + log.Fatal(err) + } + cfgReader := bytes.NewReader(j) - // TODO :- start an instance of caddy server + err = caddy2.Load(cfgReader) + if err != nil { + log.Fatal(err) + } defer runtime.HandleCrash() defer c.syncQueue.ShutDown() + defer c.statusQueue.ShutDown() // start the ingress informer where we listen to new / updated ingress resources go c.informer.Run(stopCh) @@ -111,26 +131,23 @@ func (c *CaddyController) Run(stopCh chan struct{}) { // start processing events for syncing ingress resources go wait.Until(c.runWorker, time.Second, stopCh) - // start ingress status syncher + // start ingress status syncher and run every syncInterval go wait.Until(c.dispatchSync, syncInterval, stopCh) + // wait for SIGTERM <-stopCh klog.Info("stopping ingress controller") - exitCode := 0 - err := c.Shutdown() + var exitCode int + err = c.Shutdown() if err != nil { - klog.Errorf("could not shutdown ingress controller properly") + klog.Errorf("could not shutdown ingress controller properly, %v", err.Error()) 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() { diff --git a/internal/controller/ingress.go b/internal/controller/ingress.go new file mode 100644 index 0000000..5be5957 --- /dev/null +++ b/internal/controller/ingress.go @@ -0,0 +1,98 @@ +package controller + +import ( + "fmt" + "sort" + "strings" + + "github.com/pkg/errors" + pool "gopkg.in/go-playground/pool.v3" + apiv1 "k8s.io/api/core/v1" + "k8s.io/api/extensions/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/klog" +) + +// updateIngStatuses starts a queue and adds all monitored ingresses to update their status source address to the on +// that the ingress controller is running on. This is called by the syncStatus queue. +func (c *CaddyController) updateIngStatuses(controllerAddresses []apiv1.LoadBalancerIngress, ings []*v1beta1.Ingress) { + p := pool.NewLimited(10) + defer p.Close() + + batch := p.Batch() + sort.SliceStable(controllerAddresses, lessLoadBalancerIngress(controllerAddresses)) + + for _, ing := range ings { + curIPs := ing.Status.LoadBalancer.Ingress + sort.SliceStable(curIPs, lessLoadBalancerIngress(curIPs)) + + // check to see if ingresses source address does not match the ingress controller's. + if ingressSliceEqual(curIPs, controllerAddresses) { + klog.V(3).Infof("skipping update of Ingress %v/%v (no change)", ing.Namespace, ing.Name) + continue + } + + batch.Queue(runUpdate(ing, controllerAddresses, c.kubeClient)) + } + + batch.QueueComplete() + batch.WaitAll() +} + +// runUpdate updates the ingress status field. +func runUpdate(ing *v1beta1.Ingress, status []apiv1.LoadBalancerIngress, client *kubernetes.Clientset) pool.WorkFunc { + return func(wu pool.WorkUnit) (interface{}, error) { + if wu.IsCancelled() { + return nil, nil + } + + ingClient := client.ExtensionsV1beta1().Ingresses(ing.Namespace) + + currIng, err := ingClient.Get(ing.Name, metav1.GetOptions{}) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("unexpected error searching Ingress %v/%v", ing.Namespace, ing.Name)) + } + + klog.Infof("updating Ingress %v/%v status from %v to %v", currIng.Namespace, currIng.Name, currIng.Status.LoadBalancer.Ingress, status) + currIng.Status.LoadBalancer.Ingress = status + + _, err = ingClient.UpdateStatus(currIng) + if err != nil { + klog.Warningf("error updating ingress rule: %v", err) + } + + return true, nil + } +} + +// ingressSliceEqual determines if the ingress source matches the ingress controller's. +func ingressSliceEqual(lhs, rhs []apiv1.LoadBalancerIngress) bool { + if len(lhs) != len(rhs) { + return false + } + + for i := range lhs { + if lhs[i].IP != rhs[i].IP { + return false + } + if lhs[i].Hostname != rhs[i].Hostname { + return false + } + } + + return true +} + +// lessLoadBalancerIngress is a sorting function +func lessLoadBalancerIngress(addrs []apiv1.LoadBalancerIngress) func(int, int) bool { + return func(a, b int) bool { + switch strings.Compare(addrs[a].Hostname, addrs[b].Hostname) { + case -1: + return true + case 1: + return false + } + return addrs[a].IP < addrs[b].IP + } +} diff --git a/internal/controller/status.go b/internal/controller/status.go index 8256c35..b8dd09e 100644 --- a/internal/controller/status.go +++ b/internal/controller/status.go @@ -1,9 +1,13 @@ package controller import ( - "fmt" + "net" + "sort" + "bitbucket.org/lightcodelabs/ingress/internal/pod" + apiv1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" + "k8s.io/klog" ) // dispatchSync is run every syncInterval duration to sync ingress source address fields. @@ -16,13 +20,36 @@ type SyncStatusAction struct { } func (r SyncStatusAction) handle(c *CaddyController) error { - c.syncStatus(c.resourceStore.Ingresses) - return nil + return c.syncStatus(c.resourceStore.Ingresses) } // 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 +func (c *CaddyController) syncStatus(ings []*v1beta1.Ingress) error { + addrs, err := pod.GetAddresses(c.podInfo, c.kubeClient) + if err != nil { + return err + } - fmt.Println("Handle Synching Ingress Source Address") + klog.Info("Synching Ingress resource source addresses") + c.updateIngStatuses(sliceToLoadBalancerIngress(addrs), ings) + + return nil +} + +// sliceToLoadBalancerIngress converts a slice of IP and/or hostnames to LoadBalancerIngress +func sliceToLoadBalancerIngress(endpoints []string) []apiv1.LoadBalancerIngress { + lbi := []apiv1.LoadBalancerIngress{} + for _, ep := range endpoints { + if net.ParseIP(ep) == nil { + lbi = append(lbi, apiv1.LoadBalancerIngress{Hostname: ep}) + } else { + lbi = append(lbi, apiv1.LoadBalancerIngress{IP: ep}) + } + } + + sort.SliceStable(lbi, func(a, b int) bool { + return lbi[a].IP < lbi[b].IP + }) + + return lbi } diff --git a/internal/ingress/ingress.go b/internal/ingress/ingress.go deleted file mode 100644 index ee5fd06..0000000 --- a/internal/ingress/ingress.go +++ /dev/null @@ -1,3 +0,0 @@ -package ingress - -// handle getting ingress information here diff --git a/internal/pod/pod.go b/internal/pod/pod.go new file mode 100644 index 0000000..cd6df21 --- /dev/null +++ b/internal/pod/pod.go @@ -0,0 +1,99 @@ +package pod + +import ( + "fmt" + "os" + + apiv1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/kubernetes" + "k8s.io/klog" + "k8s.io/kubernetes/pkg/kubelet/util/sliceutils" +) + +// Info contains runtime information about the pod running the Ingres controller +type Info struct { + Name string + Namespace string + // Labels selectors of the running pod + // This is used to search for other Ingress controller pods + Labels map[string]string +} + +func GetAddresses(p *Info, kubeClient *kubernetes.Clientset) ([]string, error) { + addrs := []string{} + + // get information about all the pods running the ingress controller + pods, err := kubeClient.CoreV1().Pods(p.Namespace).List(metav1.ListOptions{ + LabelSelector: labels.SelectorFromSet(p.Labels).String(), + }) + if err != nil { + return nil, err + } + + for _, pod := range pods.Items { + // only Running pods are valid + if pod.Status.Phase != apiv1.PodRunning { + continue + } + + name := GetNodeIPOrName(kubeClient, pod.Spec.NodeName, true) + if !sliceutils.StringInSlice(name, addrs) { + addrs = append(addrs, name) + } + } + + return addrs, nil +} + +// GetNodeIPOrName returns the IP address or the name of a node in the cluster +func GetNodeIPOrName(kubeClient *kubernetes.Clientset, name string, useInternalIP bool) string { + node, err := kubeClient.CoreV1().Nodes().Get(name, metav1.GetOptions{}) + if err != nil { + klog.Errorf("Error getting node %v: %v", name, err) + return "" + } + + if useInternalIP { + for _, address := range node.Status.Addresses { + if address.Type == apiv1.NodeInternalIP { + if address.Address != "" { + return address.Address + } + } + } + } + + for _, address := range node.Status.Addresses { + if address.Type == apiv1.NodeExternalIP { + if address.Address != "" { + return address.Address + } + } + } + + return "" +} + +// GetPodDetails returns runtime information about the pod: +// name, namespace and IP of the node where it is running +func GetPodDetails(kubeClient *kubernetes.Clientset) (*Info, error) { + podName := os.Getenv("POD_NAME") + podNs := os.Getenv("POD_NAMESPACE") + + if podName == "" || podNs == "" { + return nil, fmt.Errorf("unable to get POD information (missing POD_NAME or POD_NAMESPACE environment variable") + } + + pod, _ := kubeClient.CoreV1().Pods(podNs).Get(podName, metav1.GetOptions{}) + if pod == nil { + return nil, fmt.Errorf("unable to get POD information") + } + + return &Info{ + Name: podName, + Namespace: podNs, + Labels: pod.GetLabels(), + }, nil +} diff --git a/internal/store/store.go b/internal/store/store.go index 28192a1..8317a04 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -1,6 +1,7 @@ package store import ( + "bitbucket.org/lightcodelabs/ingress/internal/caddy" "k8s.io/api/extensions/v1beta1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -9,8 +10,9 @@ import ( // 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? + Ingresses []*v1beta1.Ingress + Secrets []interface{} // TODO :- should we store the secrets in the ingress object? + CaddyConfig *caddy.Config } // NewStore returns a new store that keeps track of ingresses and secrets. It will attempt to get @@ -23,7 +25,8 @@ func NewStore(kubeClient *kubernetes.Clientset) *Store { } s := &Store{ - Ingresses: make([]*v1beta1.Ingress, len(ingresses.Items)-1), + Ingresses: []*v1beta1.Ingress{}, + CaddyConfig: caddy.NewConfig(), } for _, i := range ingresses.Items { diff --git a/kubernetes/generated/clusterrole.yaml b/kubernetes/generated/clusterrole.yaml index b090c69..235e499 100644 --- a/kubernetes/generated/clusterrole.yaml +++ b/kubernetes/generated/clusterrole.yaml @@ -9,6 +9,8 @@ rules: resources: - ingresses - routes + - extensions + - ingresses/status verbs: - list - get @@ -21,6 +23,7 @@ rules: resources: - services - pods + - nodes verbs: - list - get diff --git a/kubernetes/generated/deployment.yaml b/kubernetes/generated/deployment.yaml index 95d8846..be6c760 100644 --- a/kubernetes/generated/deployment.yaml +++ b/kubernetes/generated/deployment.yaml @@ -26,9 +26,34 @@ spec: version: v0.1.0 spec: + serviceAccountName: caddyingresscontroller containers: - - env: + - name: caddyingresscontroller image: "caddy/ingresscontroller" imagePullPolicy: IfNotPresent - name: caddyingresscontroller - serviceAccountName: caddyingresscontroller \ No newline at end of file + securityContext: + allowPrivilegeEscalation: true + capabilities: + drop: + - ALL + add: + - NET_BIND_SERVICE + # www-data -> 33 + runAsUser: 0 + runAsGroup: 0 + ports: + - name: http + containerPort: 80 + hostPort: 80 # optional, required if running in minikube + - name: https + containerPort: 443 + hostPort: 443 # optional, required if running in minikube + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace \ No newline at end of file diff --git a/kubernetes/helm/caddyingresscontroller/templates/deployment.yaml b/kubernetes/helm/caddyingresscontroller/templates/deployment.yaml index b03ca33..0eb9501 100644 --- a/kubernetes/helm/caddyingresscontroller/templates/deployment.yaml +++ b/kubernetes/helm/caddyingresscontroller/templates/deployment.yaml @@ -29,12 +29,20 @@ spec: {{- 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 }}" + - image: "{{ .Values.caddyingresscontroller.image.name }}:{{ .Values.caddyingresscontroller.image.tag }}" imagePullPolicy: {{ .Values.caddyingresscontroller.image.pullPolicy }} name: {{ .Values.name }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.caddyingresscontroller.watchNamespace }} + - name: KUBERNETES_NAMESPACE + value: {{ .Values.caddyingresscontroller.watchNamespace | quote }} + {{- end }} serviceAccountName: {{ .Values.serviceAccountName }} \ No newline at end of file diff --git a/skaffold.yaml b/skaffold.yaml index ed63287..c4bdcde 100644 --- a/skaffold.yaml +++ b/skaffold.yaml @@ -6,6 +6,9 @@ build: deploy: kubectl: manifests: + - hack/test/example-deployment.yaml + - hack/test/example-ingress.yaml + - hack/test/example-service.yaml - kubernetes/generated/clusterrole.yaml - kubernetes/generated/clusterrolebinding.yaml - kubernetes/generated/deployment.yaml