From bc78a8bff5f3b664738d40eb054cb45cc5f68ee1 Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Thu, 9 Aug 2018 11:47:37 +0100 Subject: [PATCH 01/10] Refactor package layout to be more standard Following this common approach https://github.com/golang-standards/project-layout --- .gitignore | 3 +++ .travis.yml | 3 +-- CONTRIBUTING.md | 8 ++++++-- nginx-controller/Makefile => Makefile | 16 ++++++++++------ README.md | 2 +- {nginx-controller => build}/Dockerfile | 2 +- {nginx-controller => build}/DockerfileForAlpine | 0 {nginx-controller => build}/DockerfileForPlus | 0 {nginx-controller => build}/README.md | 9 +++------ {ci => build/ci}/Jenkinsfile | 0 .../generate_default_cert_and_key.sh | 0 {nginx-controller => cmd/nginx-ic}/main.go | 6 +++--- {install => deployments}/README.md | 0 .../common/default-server-secret.yaml | 0 .../common/nginx-config.yaml | 0 {install => deployments}/common/ns-and-sa.yaml | 0 .../daemon-set/nginx-ingress.yaml | 0 .../nginx-plus-ingress-with-prometheus.yaml | 0 .../daemon-set/nginx-plus-ingress.yaml | 0 .../deployment/nginx-ingress.yaml | 0 .../nginx-plus-ingress-with-prometheus.yaml | 0 .../deployment/nginx-plus-ingress.yaml | 0 .../helm-chart}/Chart.yaml | 0 {helm-chart => deployments/helm-chart}/README.md | 2 +- .../helm-chart}/templates/NOTES.txt | 0 .../templates/controller-configmap.yaml | 0 .../templates/controller-daemonset.yaml | 0 .../templates/controller-deployment.yaml | 0 .../helm-chart}/templates/controller-secret.yaml | 0 .../templates/controller-service.yaml | 0 .../templates/controller-serviceaccount.yaml | 0 .../helm-chart}/templates/rbac.yaml | 0 .../helm-chart}/values-icp.yaml | 0 .../helm-chart}/values-plus.yaml | 0 .../helm-chart}/values.yaml | 0 {install => deployments}/rbac/rbac.yaml | 0 .../service/loadbalancer-aws-elb.yaml | 0 .../service/loadbalancer.yaml | 0 {install => deployments}/service/nodeport.yaml | 0 docs/installation.md | 2 +- docs/nginx-ingress-controllers.md | 2 +- examples/openshift/README.md | 12 ++++++------ .../controller/controller.go | 2 +- .../controller/controller_test.go | 4 ++-- .../controller/leader.go | 0 .../controller/status.go | 2 +- .../controller/status_test.go | 0 .../controller/utils.go | 0 {nginx-controller => internal}/nginx/config.go | 0 .../nginx/configurator.go | 2 +- .../nginx/configurator_test.go | 2 +- {nginx-controller => internal}/nginx/convert.go | 0 .../nginx/convert_test.go | 0 .../nginx/extensions.go | 0 .../nginx/extensions_test.go | 0 {nginx-controller => internal}/nginx/ingress.go | 0 {nginx-controller => internal}/nginx/nginx.go | 0 .../nginx/plus/nginx_api.go | 0 .../nginx/plus/nginx_client.go | 0 {nginx-controller => internal}/nginx/secret.go | 0 .../nginx/template_executor.go | 0 .../nginx/templates/nginx-plus.ingress.tmpl | 0 .../nginx/templates/nginx-plus.tmpl | 0 .../nginx/templates/nginx.ingress.tmpl | 0 .../nginx/templates/nginx.tmpl | 0 .../nginx/templates/templates_test.go | 2 +- 66 files changed, 44 insertions(+), 37 deletions(-) rename nginx-controller/Makefile => Makefile (56%) rename {nginx-controller => build}/Dockerfile (84%) rename {nginx-controller => build}/DockerfileForAlpine (100%) rename {nginx-controller => build}/DockerfileForPlus (100%) rename {nginx-controller => build}/README.md (97%) rename {ci => build/ci}/Jenkinsfile (100%) rename {nginx-controller => build}/generate_default_cert_and_key.sh (100%) rename {nginx-controller => cmd/nginx-ic}/main.go (98%) rename {install => deployments}/README.md (100%) rename {install => deployments}/common/default-server-secret.yaml (100%) rename {install => deployments}/common/nginx-config.yaml (100%) rename {install => deployments}/common/ns-and-sa.yaml (100%) rename {install => deployments}/daemon-set/nginx-ingress.yaml (100%) rename {install => deployments}/daemon-set/nginx-plus-ingress-with-prometheus.yaml (100%) rename {install => deployments}/daemon-set/nginx-plus-ingress.yaml (100%) rename {install => deployments}/deployment/nginx-ingress.yaml (100%) rename {install => deployments}/deployment/nginx-plus-ingress-with-prometheus.yaml (100%) rename {install => deployments}/deployment/nginx-plus-ingress.yaml (100%) rename {helm-chart => deployments/helm-chart}/Chart.yaml (100%) rename {helm-chart => deployments/helm-chart}/README.md (99%) rename {helm-chart => deployments/helm-chart}/templates/NOTES.txt (100%) rename {helm-chart => deployments/helm-chart}/templates/controller-configmap.yaml (100%) rename {helm-chart => deployments/helm-chart}/templates/controller-daemonset.yaml (100%) rename {helm-chart => deployments/helm-chart}/templates/controller-deployment.yaml (100%) rename {helm-chart => deployments/helm-chart}/templates/controller-secret.yaml (100%) rename {helm-chart => deployments/helm-chart}/templates/controller-service.yaml (100%) rename {helm-chart => deployments/helm-chart}/templates/controller-serviceaccount.yaml (100%) rename {helm-chart => deployments/helm-chart}/templates/rbac.yaml (100%) rename {helm-chart => deployments/helm-chart}/values-icp.yaml (100%) rename {helm-chart => deployments/helm-chart}/values-plus.yaml (100%) rename {helm-chart => deployments/helm-chart}/values.yaml (100%) rename {install => deployments}/rbac/rbac.yaml (100%) rename {install => deployments}/service/loadbalancer-aws-elb.yaml (100%) rename {install => deployments}/service/loadbalancer.yaml (100%) rename {install => deployments}/service/nodeport.yaml (100%) rename {nginx-controller => internal}/controller/controller.go (99%) rename {nginx-controller => internal}/controller/controller_test.go (99%) rename {nginx-controller => internal}/controller/leader.go (100%) rename {nginx-controller => internal}/controller/status.go (99%) rename {nginx-controller => internal}/controller/status_test.go (100%) rename {nginx-controller => internal}/controller/utils.go (100%) rename {nginx-controller => internal}/nginx/config.go (100%) rename {nginx-controller => internal}/nginx/configurator.go (99%) rename {nginx-controller => internal}/nginx/configurator_test.go (99%) rename {nginx-controller => internal}/nginx/convert.go (100%) rename {nginx-controller => internal}/nginx/convert_test.go (100%) rename {nginx-controller => internal}/nginx/extensions.go (100%) rename {nginx-controller => internal}/nginx/extensions_test.go (100%) rename {nginx-controller => internal}/nginx/ingress.go (100%) rename {nginx-controller => internal}/nginx/nginx.go (100%) rename {nginx-controller => internal}/nginx/plus/nginx_api.go (100%) rename {nginx-controller => internal}/nginx/plus/nginx_client.go (100%) rename {nginx-controller => internal}/nginx/secret.go (100%) rename {nginx-controller => internal}/nginx/template_executor.go (100%) rename {nginx-controller => internal}/nginx/templates/nginx-plus.ingress.tmpl (100%) rename {nginx-controller => internal}/nginx/templates/nginx-plus.tmpl (100%) rename {nginx-controller => internal}/nginx/templates/nginx.ingress.tmpl (100%) rename {nginx-controller => internal}/nginx/templates/nginx.tmpl (100%) rename {nginx-controller => internal}/nginx/templates/templates_test.go (98%) diff --git a/.gitignore b/.gitignore index 31d3d3e3a5..ec3e8490c5 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,6 @@ nginx-controller/nginx-controller # Default certificate and key default.pem + +# Dockerfiles for building +Dockerfile diff --git a/.travis.yml b/.travis.yml index a0acd2bf51..811bf0b568 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,7 @@ go: - "1.10" script: - echo "Building ingress controller commit:${TRAVIS_COMMIT}" -- cd nginx-controller && - make BUILD_IN_CONTAINER=0 container; +- make BUILD_IN_CONTAINER=0 container; before_install: - echo "PR Slug:${TRAVIS_PULL_REQUEST_SLUG}" - if [[ "${TRAVIS_PULL_REQUEST_SLUG}" == "nginxinc/kubernetes-ingress" || "${TRAVIS_PULL_REQUEST}" == "false" ]]; then diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d905c537bd..67580f866b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,8 +30,12 @@ Read the [documentation](https://github.com/nginxinc/kubernetes-ingress/tree/mas ### Project Structure * This Ingress Controller is written in Go and supports both the open source NGINX software and NGINX Plus. -* The main code resides under `/nginx-controller` -* The project dependencies reside in the `/vendor`. We use [dep](https://github.com/golang/dep) for managing dependencies. +* The project follows a standard Go project layout + * The main code is found at `cmd/nginx-ic/` + * The internal code is found at `internal/` + * Build files for Docker and CI are found under `build/` + * Deployment yaml files, and Helm files are found at `deployments/` + * The project dependencies are found at `vendor/`. We use [dep](https://github.com/golang/dep) for managing dependencies. ## Contributing diff --git a/nginx-controller/Makefile b/Makefile similarity index 56% rename from nginx-controller/Makefile rename to Makefile index d2c6e77241..91d3cb118d 100644 --- a/nginx-controller/Makefile +++ b/Makefile @@ -4,22 +4,24 @@ VERSION = edge TAG = $(VERSION) PREFIX = nginx/nginx-ingress -DOCKER_RUN = docker run --rm -v $(shell pwd)/../:/go/src/github.com/nginxinc/kubernetes-ingress -w /go/src/github.com/nginxinc/kubernetes-ingress/nginx-controller/ +DOCKER_RUN = docker run --rm -v $(shell pwd):/go/src/github.com/nginxinc/kubernetes-ingress +DOCKER_BUILD_RUN = docker run --rm -v $(shell pwd):/go/src/github.com/nginxinc/kubernetes-ingress -w /go/src/github.com/nginxinc/kubernetes-ingress/cmd/nginx-ic/ GOLANG_CONTAINER = golang:1.10 +DOCKERFILEPATH = build DOCKERFILE = Dockerfile BUILD_IN_CONTAINER = 1 PUSH_TO_GCR = -GENERATE_DEFAULT_CERT_AND_KEY = +GENERATE_DEFAULT_CERT_AND_KEY = DOCKER_BUILD_OPTIONS = GIT_COMMIT=$(shell git rev-parse --short HEAD) nginx-ingress: ifeq ($(BUILD_IN_CONTAINER),1) - $(DOCKER_RUN) -e CGO_ENABLED=0 $(GOLANG_CONTAINER) go build -a -installsuffix cgo -ldflags "-w -X main.version=${VERSION} -X main.gitCommit=${GIT_COMMIT}" -o nginx-ingress *.go + $(DOCKER_BUILD_RUN) -e CGO_ENABLED=0 $(GOLANG_CONTAINER) go build -a -installsuffix cgo -ldflags "-w -X main.version=${VERSION} -X main.gitCommit=${GIT_COMMIT}" -o /go/src/github.com/nginxinc/kubernetes-ingress/nginx-ingress else - CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags "-w -X main.version=${VERSION} -X main.gitCommit=${GIT_COMMIT}" -o nginx-ingress *.go + CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags "-w -X main.version=${VERSION} -X main.gitCommit=${GIT_COMMIT}" -o nginx-ingress endif test: @@ -29,12 +31,13 @@ else go test ./... endif -certificate-and-key: +certificate-and-key: ifeq ($(GENERATE_DEFAULT_CERT_AND_KEY),1) - ./generate_default_cert_and_key.sh + ./build/generate_default_cert_and_key.sh endif container: test nginx-ingress certificate-and-key + cp $(DOCKERFILEPATH)/$(DOCKERFILE) . docker build $(DOCKER_BUILD_OPTIONS) -f $(DOCKERFILE) -t $(PREFIX):$(TAG) . push: container @@ -46,3 +49,4 @@ endif clean: rm -f nginx-ingress + rm $(DOCKERFILE) diff --git a/README.md b/README.md index 336a7e08eb..2163120961 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ NGINX Plus provides you with [advanced statistics](https://www.nginx.com/product * **JWTs** NGINX Plus can validate JSON Web Tokens (JWTs), providing a flexible authentication mechanism. * **Support** Support from NGINX Inc is available for NGINX Plus Ingress controller. -**Note**: Deployment of the Ingress controller for NGINX Plus requires you to do one extra step: build your own [Docker image](nginx-controller) using the certificate and key for your subscription. +**Note**: Deployment of the Ingress controller for NGINX Plus requires you to do one extra step: build your own [Docker image](build) using the certificate and key for your subscription. The Docker image of the Ingress controller for NGINX is [available on Docker Hub](https://hub.docker.com/r/nginx/nginx-ingress/). ## Using Multiple Ingress Controllers diff --git a/nginx-controller/Dockerfile b/build/Dockerfile similarity index 84% rename from nginx-controller/Dockerfile rename to build/Dockerfile index d3e5ffebf1..e640656675 100644 --- a/nginx-controller/Dockerfile +++ b/build/Dockerfile @@ -6,7 +6,7 @@ RUN ln -sf /proc/1/fd/1 /var/log/nginx/access.log \ && ln -sf /proc/1/fd/1 /var/log/nginx/stream-access.log \ && ln -sf /proc/1/fd/2 /var/log/nginx/error.log -COPY nginx-ingress nginx/templates/nginx.ingress.tmpl nginx/templates/nginx.tmpl / +COPY nginx-ingress internal/nginx/templates/nginx.ingress.tmpl internal/nginx/templates/nginx.tmpl / RUN rm /etc/nginx/conf.d/* diff --git a/nginx-controller/DockerfileForAlpine b/build/DockerfileForAlpine similarity index 100% rename from nginx-controller/DockerfileForAlpine rename to build/DockerfileForAlpine diff --git a/nginx-controller/DockerfileForPlus b/build/DockerfileForPlus similarity index 100% rename from nginx-controller/DockerfileForPlus rename to build/DockerfileForPlus diff --git a/nginx-controller/README.md b/build/README.md similarity index 97% rename from nginx-controller/README.md rename to build/README.md index f2069a94ef..82b3c3efc2 100644 --- a/nginx-controller/README.md +++ b/build/README.md @@ -23,14 +23,13 @@ Although the Ingress controller is written in golang, golang is not required, as ### Building the Image and Pushing It to the Private Registry -We build the image using the make utility and the provided `Makefile`. Let’s create the controller binary, build an image and push the image to the private registry. +We build the image using the make utility and the provided `Makefile`. Let’s create the controller binary, build an image and push the image to the private registry. 1. Make sure to run the `docker login` command first to login to the registry. If you’re using Google Container Registry, you don’t need to use the docker command to login -- make sure you’re logged into the gcloud tool (using the `gcloud auth login` command) and set the variable `PUSH_TO_GCR=1` when running the make command. -1. Clone the Ingress controller repo and change your folder to `nginx-controller`: +1. Clone the Ingress controller repo: ``` $ git clone https://github.com/nginxinc/kubernetes-ingress/ - $ cd kubernetes-ingress/nginx-controller ``` 1. If you're using a stable release, check out the corresponding tag. For release 1.3.0, run: @@ -84,10 +83,8 @@ The **Makefile** contains the following main variables for you to customize (eit 1. `Dockerfile`, for building a debian-based image with NGINX. It's used by default. 1. `DockerfileForAlpine`, for building an alpine-based image with NGINX. 1. `DockerfileForPlus`, for building an debian-based image with NGINX Plus. -* **GENERATE_DEFAULT_CERT_AND_KEY** - The Ingress controller requires a certificate and a key for the default HTTP/HTTPS server. You can reference them in a TLS Secret in a command-line argument to the Ingress controller. As an alternative, you can add a file in the PEM format with your certificate and key to the image as `/etc/nginx/secrets/default`. Optionally, you can generate a self-signed certificate and a key during the build process. Set `GENERATE_DEFAULT_CERT_AND_KEY` to `1` to generate a certificate and a key in the `default.pem` file. Note that you must add the `ADD` instruction in the Dockerfile to copy the cert and the key to the image. The default value of `GENERATE_DEFAULT_CERT_AND_KEY` is `0`. +* **GENERATE_DEFAULT_CERT_AND_KEY** - The Ingress controller requires a certificate and a key for the default HTTP/HTTPS server. You can reference them in a TLS Secret in a command-line argument to the Ingress controller. As an alternative, you can add a file in the PEM format with your certificate and key to the image as `/etc/nginx/secrets/default`. Optionally, you can generate a self-signed certificate and a key during the build process. Set `GENERATE_DEFAULT_CERT_AND_KEY` to `1` to generate a certificate and a key in the `default.pem` file. Note that you must add the `ADD` instruction in the Dockerfile to copy the cert and the key to the image. The default value of `GENERATE_DEFAULT_CERT_AND_KEY` is `0`. * **DOCKER_BUILD_OPTIONS** -- the [options](https://docs.docker.com/engine/reference/commandline/build/#options) for the `docker build` command. For example, `--pull`. * **BUILD_IN_CONTAINER** -- By default, to compile the controller we use the [golang](https://hub.docker.com/_/golang/) container that we run as part of the building process. If you want to compile the controller using your local golang environment: 1. Make sure that the Ingress controller repo is in your `$GOPATH`. 1. Specify `BUILD_IN_CONTAINER=0` when you run the make command. - - diff --git a/ci/Jenkinsfile b/build/ci/Jenkinsfile similarity index 100% rename from ci/Jenkinsfile rename to build/ci/Jenkinsfile diff --git a/nginx-controller/generate_default_cert_and_key.sh b/build/generate_default_cert_and_key.sh similarity index 100% rename from nginx-controller/generate_default_cert_and_key.sh rename to build/generate_default_cert_and_key.sh diff --git a/nginx-controller/main.go b/cmd/nginx-ic/main.go similarity index 98% rename from nginx-controller/main.go rename to cmd/nginx-ic/main.go index 90d3358fb3..2ae44e662e 100644 --- a/nginx-controller/main.go +++ b/cmd/nginx-ic/main.go @@ -13,9 +13,9 @@ import ( "github.com/golang/glog" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/controller" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx/plus" + "github.com/nginxinc/kubernetes-ingress/internal/controller" + "github.com/nginxinc/kubernetes-ingress/internal/nginx" + "github.com/nginxinc/kubernetes-ingress/internal/nginx/plus" api_v1 "k8s.io/api/core/v1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" diff --git a/install/README.md b/deployments/README.md similarity index 100% rename from install/README.md rename to deployments/README.md diff --git a/install/common/default-server-secret.yaml b/deployments/common/default-server-secret.yaml similarity index 100% rename from install/common/default-server-secret.yaml rename to deployments/common/default-server-secret.yaml diff --git a/install/common/nginx-config.yaml b/deployments/common/nginx-config.yaml similarity index 100% rename from install/common/nginx-config.yaml rename to deployments/common/nginx-config.yaml diff --git a/install/common/ns-and-sa.yaml b/deployments/common/ns-and-sa.yaml similarity index 100% rename from install/common/ns-and-sa.yaml rename to deployments/common/ns-and-sa.yaml diff --git a/install/daemon-set/nginx-ingress.yaml b/deployments/daemon-set/nginx-ingress.yaml similarity index 100% rename from install/daemon-set/nginx-ingress.yaml rename to deployments/daemon-set/nginx-ingress.yaml diff --git a/install/daemon-set/nginx-plus-ingress-with-prometheus.yaml b/deployments/daemon-set/nginx-plus-ingress-with-prometheus.yaml similarity index 100% rename from install/daemon-set/nginx-plus-ingress-with-prometheus.yaml rename to deployments/daemon-set/nginx-plus-ingress-with-prometheus.yaml diff --git a/install/daemon-set/nginx-plus-ingress.yaml b/deployments/daemon-set/nginx-plus-ingress.yaml similarity index 100% rename from install/daemon-set/nginx-plus-ingress.yaml rename to deployments/daemon-set/nginx-plus-ingress.yaml diff --git a/install/deployment/nginx-ingress.yaml b/deployments/deployment/nginx-ingress.yaml similarity index 100% rename from install/deployment/nginx-ingress.yaml rename to deployments/deployment/nginx-ingress.yaml diff --git a/install/deployment/nginx-plus-ingress-with-prometheus.yaml b/deployments/deployment/nginx-plus-ingress-with-prometheus.yaml similarity index 100% rename from install/deployment/nginx-plus-ingress-with-prometheus.yaml rename to deployments/deployment/nginx-plus-ingress-with-prometheus.yaml diff --git a/install/deployment/nginx-plus-ingress.yaml b/deployments/deployment/nginx-plus-ingress.yaml similarity index 100% rename from install/deployment/nginx-plus-ingress.yaml rename to deployments/deployment/nginx-plus-ingress.yaml diff --git a/helm-chart/Chart.yaml b/deployments/helm-chart/Chart.yaml similarity index 100% rename from helm-chart/Chart.yaml rename to deployments/helm-chart/Chart.yaml diff --git a/helm-chart/README.md b/deployments/helm-chart/README.md similarity index 99% rename from helm-chart/README.md rename to deployments/helm-chart/README.md index 92f6dfd231..fdf82847c3 100644 --- a/helm-chart/README.md +++ b/deployments/helm-chart/README.md @@ -10,7 +10,7 @@ This chart deploys the NGINX Ingress controller in your Kubernetes cluster. - Helm 2.8.x+. - Git. - If you’d like to use NGINX Plus: - - Build an Ingress controller image with NGINX Plus and push it to your private registry by following the instructions from [here](../nginx-controller/README.md). + - Build an Ingress controller image with NGINX Plus and push it to your private registry by following the instructions from [here](../../build/README.md). - Update the `controller.image.repository` field of the `values-plus.yaml` accordingly. ## Installing the Chart diff --git a/helm-chart/templates/NOTES.txt b/deployments/helm-chart/templates/NOTES.txt similarity index 100% rename from helm-chart/templates/NOTES.txt rename to deployments/helm-chart/templates/NOTES.txt diff --git a/helm-chart/templates/controller-configmap.yaml b/deployments/helm-chart/templates/controller-configmap.yaml similarity index 100% rename from helm-chart/templates/controller-configmap.yaml rename to deployments/helm-chart/templates/controller-configmap.yaml diff --git a/helm-chart/templates/controller-daemonset.yaml b/deployments/helm-chart/templates/controller-daemonset.yaml similarity index 100% rename from helm-chart/templates/controller-daemonset.yaml rename to deployments/helm-chart/templates/controller-daemonset.yaml diff --git a/helm-chart/templates/controller-deployment.yaml b/deployments/helm-chart/templates/controller-deployment.yaml similarity index 100% rename from helm-chart/templates/controller-deployment.yaml rename to deployments/helm-chart/templates/controller-deployment.yaml diff --git a/helm-chart/templates/controller-secret.yaml b/deployments/helm-chart/templates/controller-secret.yaml similarity index 100% rename from helm-chart/templates/controller-secret.yaml rename to deployments/helm-chart/templates/controller-secret.yaml diff --git a/helm-chart/templates/controller-service.yaml b/deployments/helm-chart/templates/controller-service.yaml similarity index 100% rename from helm-chart/templates/controller-service.yaml rename to deployments/helm-chart/templates/controller-service.yaml diff --git a/helm-chart/templates/controller-serviceaccount.yaml b/deployments/helm-chart/templates/controller-serviceaccount.yaml similarity index 100% rename from helm-chart/templates/controller-serviceaccount.yaml rename to deployments/helm-chart/templates/controller-serviceaccount.yaml diff --git a/helm-chart/templates/rbac.yaml b/deployments/helm-chart/templates/rbac.yaml similarity index 100% rename from helm-chart/templates/rbac.yaml rename to deployments/helm-chart/templates/rbac.yaml diff --git a/helm-chart/values-icp.yaml b/deployments/helm-chart/values-icp.yaml similarity index 100% rename from helm-chart/values-icp.yaml rename to deployments/helm-chart/values-icp.yaml diff --git a/helm-chart/values-plus.yaml b/deployments/helm-chart/values-plus.yaml similarity index 100% rename from helm-chart/values-plus.yaml rename to deployments/helm-chart/values-plus.yaml diff --git a/helm-chart/values.yaml b/deployments/helm-chart/values.yaml similarity index 100% rename from helm-chart/values.yaml rename to deployments/helm-chart/values.yaml diff --git a/install/rbac/rbac.yaml b/deployments/rbac/rbac.yaml similarity index 100% rename from install/rbac/rbac.yaml rename to deployments/rbac/rbac.yaml diff --git a/install/service/loadbalancer-aws-elb.yaml b/deployments/service/loadbalancer-aws-elb.yaml similarity index 100% rename from install/service/loadbalancer-aws-elb.yaml rename to deployments/service/loadbalancer-aws-elb.yaml diff --git a/install/service/loadbalancer.yaml b/deployments/service/loadbalancer.yaml similarity index 100% rename from install/service/loadbalancer.yaml rename to deployments/service/loadbalancer.yaml diff --git a/install/service/nodeport.yaml b/deployments/service/nodeport.yaml similarity index 100% rename from install/service/nodeport.yaml rename to deployments/service/nodeport.yaml diff --git a/docs/installation.md b/docs/installation.md index bdc8dfd9a0..7058e0e099 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -5,7 +5,7 @@ Make sure you have access to the Ingress controller image: * For NGINX Ingress controller, use the image `nginx/nginx-ingress` from [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/). -* For NGINX Plus Ingress controller, build your own image and push it to your private Docker registry by following the instructions from [here](../nginx-controller). +* For NGINX Plus Ingress controller, build your own image and push it to your private Docker registry by following the instructions from [here](../build/README.md). The installation manifests are located in the [install](../install) folder. In the steps below we assume that you will be running the commands from that folder. diff --git a/docs/nginx-ingress-controllers.md b/docs/nginx-ingress-controllers.md index adf0b88fa4..f25a0ff6df 100644 --- a/docs/nginx-ingress-controllers.md +++ b/docs/nginx-ingress-controllers.md @@ -25,7 +25,7 @@ The table below summarizes the key difference between nginxinc/kubernetes-ingres | TCP SSL Passthrough | Supported via a ConfigMap | Not supported | Not supported | | JWT validation | Not supported | Not supported | Supported | | Session persistence | Supported via a third-party module | Not supported | Supported | -| Configuration templates *1 | See the [template](https://github.com/kubernetes/ingress-nginx/blob/master/rootfs/etc/nginx/template/nginx.tmpl) | See the [templates](https://github.com/nginxinc/kubernetes-ingress/tree/master/nginx-controller/nginx/templates) | See the [templates](https://github.com/nginxinc/kubernetes-ingress/tree/master/nginx-controller/nginx/templates) | +| Configuration templates *1 | See the [template](https://github.com/kubernetes/ingress-nginx/blob/master/rootfs/etc/nginx/template/nginx.tmpl) | See the [templates](https://github.com/nginxinc/kubernetes-ingress/tree/master/internal/nginx/templates) | See the [templates](https://github.com/nginxinc/kubernetes-ingress/tree/master/internal/nginx/templates) | | **Deployment** | | Command-line arguments *2 | See the [arguments](https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/cli-arguments.md) | See the [arguments](cli-arguments.md) | See the [arguments](cli-arguments.md) | | TLS certificate and key for the default server | Required as a command-line argument/ auto-generated | Required as a command-line argument | Required as a command-line argument | diff --git a/examples/openshift/README.md b/examples/openshift/README.md index 129c3b51cc..68172e5fce 100644 --- a/examples/openshift/README.md +++ b/examples/openshift/README.md @@ -2,17 +2,17 @@ ## Prerequisites -* A cluster with OpenShift Release 3.5 and above. +* A cluster with OpenShift Release 3.5 and above. * You must be the cluster administrator to deploy the Ingress controller. * For NGINX Plus: - * Build and make available in your cluster the [Ingress controller](../../nginx-controller) image. + * Build and make available in your cluster the [Ingress controller](../../build) image. * Update the container image field in the `nginx-plus-ingress-rc.yaml` file accordingly. ## Steps 1. Avoid conflicts with the OpenShift Router. - + NGINX Plus Ingress controller must be able to bind to ports 80 and 443 of the cluster node, where it is running, like the OpenShift Router. Thus, you need to make sure that the Ingress controller and the Router are running on separate nodes. Additionally, NGINX Plus binds to port 8080 to expose its API and the monitoring dashboard. To quickly disable the Router you can run: @@ -27,7 +27,7 @@ 1. Create a service account for the Ingress controller with the name *nginx-ingress*: ``` - $ oc create sa nginx-ingress + $ oc create sa nginx-ingress ``` 1. Create a cluster role for the Ingress controller: ``` @@ -62,7 +62,7 @@ $ oc create -f ingress-admin-role.yaml ``` - Add this role to the users. As an example, we add this role for the user *developer* from the project *myproject*. + Add this role to the users. As an example, we add this role for the user *developer* from the project *myproject*. ``` $ oc policy add-role-to-user ingress-admin developer -n myproject ``` @@ -71,4 +71,4 @@ $ oc adm policy add-scc-to-user anyuid -z default -n myproject ``` -1. Now you can login as the user *developer* to the project *myproject* and [deploy the Cafe application](../complete-example#2-deploy-the-cafe-application). \ No newline at end of file +1. Now you can login as the user *developer* to the project *myproject* and [deploy the Cafe application](../complete-example#2-deploy-the-cafe-application). diff --git a/nginx-controller/controller/controller.go b/internal/controller/controller.go similarity index 99% rename from nginx-controller/controller/controller.go rename to internal/controller/controller.go index d10c4165f0..9fe5372f4b 100644 --- a/nginx-controller/controller/controller.go +++ b/internal/controller/controller.go @@ -24,7 +24,7 @@ import ( "github.com/golang/glog" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx" + "github.com/nginxinc/kubernetes-ingress/internal/nginx" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" diff --git a/nginx-controller/controller/controller_test.go b/internal/controller/controller_test.go similarity index 99% rename from nginx-controller/controller/controller_test.go rename to internal/controller/controller_test.go index 604cf01e67..64f2697e9f 100644 --- a/nginx-controller/controller/controller_test.go +++ b/internal/controller/controller_test.go @@ -8,8 +8,8 @@ import ( "time" "unsafe" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx/plus" + "github.com/nginxinc/kubernetes-ingress/internal/nginx" + "github.com/nginxinc/kubernetes-ingress/internal/nginx/plus" "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/nginx-controller/controller/leader.go b/internal/controller/leader.go similarity index 100% rename from nginx-controller/controller/leader.go rename to internal/controller/leader.go diff --git a/nginx-controller/controller/status.go b/internal/controller/status.go similarity index 99% rename from nginx-controller/controller/status.go rename to internal/controller/status.go index 1df796d7c8..70151bb4b4 100644 --- a/nginx-controller/controller/status.go +++ b/internal/controller/status.go @@ -6,7 +6,7 @@ import ( "reflect" "github.com/golang/glog" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx" + "github.com/nginxinc/kubernetes-ingress/internal/nginx" api_v1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/nginx-controller/controller/status_test.go b/internal/controller/status_test.go similarity index 100% rename from nginx-controller/controller/status_test.go rename to internal/controller/status_test.go diff --git a/nginx-controller/controller/utils.go b/internal/controller/utils.go similarity index 100% rename from nginx-controller/controller/utils.go rename to internal/controller/utils.go diff --git a/nginx-controller/nginx/config.go b/internal/nginx/config.go similarity index 100% rename from nginx-controller/nginx/config.go rename to internal/nginx/config.go diff --git a/nginx-controller/nginx/configurator.go b/internal/nginx/configurator.go similarity index 99% rename from nginx-controller/nginx/configurator.go rename to internal/nginx/configurator.go index 1f002a7297..8a72d79822 100644 --- a/nginx-controller/nginx/configurator.go +++ b/internal/nginx/configurator.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/golang/glog" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx/plus" + "github.com/nginxinc/kubernetes-ingress/internal/nginx/plus" api_v1 "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/nginx-controller/nginx/configurator_test.go b/internal/nginx/configurator_test.go similarity index 99% rename from nginx-controller/nginx/configurator_test.go rename to internal/nginx/configurator_test.go index f63f4688f1..f0ae5a66cb 100644 --- a/nginx-controller/nginx/configurator_test.go +++ b/internal/nginx/configurator_test.go @@ -6,7 +6,7 @@ import ( "sort" "testing" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx/plus" + "github.com/nginxinc/kubernetes-ingress/internal/nginx/plus" api_v1 "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" diff --git a/nginx-controller/nginx/convert.go b/internal/nginx/convert.go similarity index 100% rename from nginx-controller/nginx/convert.go rename to internal/nginx/convert.go diff --git a/nginx-controller/nginx/convert_test.go b/internal/nginx/convert_test.go similarity index 100% rename from nginx-controller/nginx/convert_test.go rename to internal/nginx/convert_test.go diff --git a/nginx-controller/nginx/extensions.go b/internal/nginx/extensions.go similarity index 100% rename from nginx-controller/nginx/extensions.go rename to internal/nginx/extensions.go diff --git a/nginx-controller/nginx/extensions_test.go b/internal/nginx/extensions_test.go similarity index 100% rename from nginx-controller/nginx/extensions_test.go rename to internal/nginx/extensions_test.go diff --git a/nginx-controller/nginx/ingress.go b/internal/nginx/ingress.go similarity index 100% rename from nginx-controller/nginx/ingress.go rename to internal/nginx/ingress.go diff --git a/nginx-controller/nginx/nginx.go b/internal/nginx/nginx.go similarity index 100% rename from nginx-controller/nginx/nginx.go rename to internal/nginx/nginx.go diff --git a/nginx-controller/nginx/plus/nginx_api.go b/internal/nginx/plus/nginx_api.go similarity index 100% rename from nginx-controller/nginx/plus/nginx_api.go rename to internal/nginx/plus/nginx_api.go diff --git a/nginx-controller/nginx/plus/nginx_client.go b/internal/nginx/plus/nginx_client.go similarity index 100% rename from nginx-controller/nginx/plus/nginx_client.go rename to internal/nginx/plus/nginx_client.go diff --git a/nginx-controller/nginx/secret.go b/internal/nginx/secret.go similarity index 100% rename from nginx-controller/nginx/secret.go rename to internal/nginx/secret.go diff --git a/nginx-controller/nginx/template_executor.go b/internal/nginx/template_executor.go similarity index 100% rename from nginx-controller/nginx/template_executor.go rename to internal/nginx/template_executor.go diff --git a/nginx-controller/nginx/templates/nginx-plus.ingress.tmpl b/internal/nginx/templates/nginx-plus.ingress.tmpl similarity index 100% rename from nginx-controller/nginx/templates/nginx-plus.ingress.tmpl rename to internal/nginx/templates/nginx-plus.ingress.tmpl diff --git a/nginx-controller/nginx/templates/nginx-plus.tmpl b/internal/nginx/templates/nginx-plus.tmpl similarity index 100% rename from nginx-controller/nginx/templates/nginx-plus.tmpl rename to internal/nginx/templates/nginx-plus.tmpl diff --git a/nginx-controller/nginx/templates/nginx.ingress.tmpl b/internal/nginx/templates/nginx.ingress.tmpl similarity index 100% rename from nginx-controller/nginx/templates/nginx.ingress.tmpl rename to internal/nginx/templates/nginx.ingress.tmpl diff --git a/nginx-controller/nginx/templates/nginx.tmpl b/internal/nginx/templates/nginx.tmpl similarity index 100% rename from nginx-controller/nginx/templates/nginx.tmpl rename to internal/nginx/templates/nginx.tmpl diff --git a/nginx-controller/nginx/templates/templates_test.go b/internal/nginx/templates/templates_test.go similarity index 98% rename from nginx-controller/nginx/templates/templates_test.go rename to internal/nginx/templates/templates_test.go index 27796d538e..db02b9faad 100644 --- a/nginx-controller/nginx/templates/templates_test.go +++ b/internal/nginx/templates/templates_test.go @@ -5,7 +5,7 @@ import ( "testing" "text/template" - "github.com/nginxinc/kubernetes-ingress/nginx-controller/nginx" + "github.com/nginxinc/kubernetes-ingress/internal/nginx" ) const nginxIngressTmpl = "nginx.ingress.tmpl" From ee6bf878525aca7d9956e3dbd2af21945cd3e79b Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Wed, 5 Sep 2018 10:02:41 +0100 Subject: [PATCH 02/10] Update gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ec3e8490c5..d8c50dc81e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,7 @@ osx-nginx-ingress nginx-ingress osx-nginx-plus-ingress nginx-plus-ingress -nginx-controller/nginx-controller +cmd/nginx-ic/nginx-ic # NGINX Plus license files *.crt From 3a8b9fd03786cf8ce69e5a3bb84a8fb1d1a4ff6f Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Wed, 5 Sep 2018 11:06:31 +0100 Subject: [PATCH 03/10] Fix broken test from not moving test file for main --- {nginx-controller => cmd/nginx-ic}/main_test.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {nginx-controller => cmd/nginx-ic}/main_test.go (100%) diff --git a/nginx-controller/main_test.go b/cmd/nginx-ic/main_test.go similarity index 100% rename from nginx-controller/main_test.go rename to cmd/nginx-ic/main_test.go From 5e6643768615be3276a572f1b24473da07d70d49 Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Fri, 10 Aug 2018 11:49:51 +0100 Subject: [PATCH 04/10] More refactoring, mainly tidy up of controller --- .gitignore | 1 + Makefile | 2 +- cmd/{nginx-ic => nginx-ingress}/main.go | 26 +- internal/controller/controller.go | 549 +++++++++++++----------- internal/controller/controller_test.go | 58 +-- internal/controller/utils.go | 22 +- 6 files changed, 346 insertions(+), 312 deletions(-) rename cmd/{nginx-ic => nginx-ingress}/main.go (94%) diff --git a/.gitignore b/.gitignore index d8c50dc81e..820e61d81b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ Session.vim # Ingress Controller binaries osx-nginx-ingress nginx-ingress +!nginx-ingress/ osx-nginx-plus-ingress nginx-plus-ingress cmd/nginx-ic/nginx-ic diff --git a/Makefile b/Makefile index 91d3cb118d..f8633bad11 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ TAG = $(VERSION) PREFIX = nginx/nginx-ingress DOCKER_RUN = docker run --rm -v $(shell pwd):/go/src/github.com/nginxinc/kubernetes-ingress -DOCKER_BUILD_RUN = docker run --rm -v $(shell pwd):/go/src/github.com/nginxinc/kubernetes-ingress -w /go/src/github.com/nginxinc/kubernetes-ingress/cmd/nginx-ic/ +DOCKER_BUILD_RUN = docker run --rm -v $(shell pwd):/go/src/github.com/nginxinc/kubernetes-ingress -w /go/src/github.com/nginxinc/kubernetes-ingress/cmd/nginx-ingress/ GOLANG_CONTAINER = golang:1.10 DOCKERFILEPATH = build DOCKERFILE = Dockerfile diff --git a/cmd/nginx-ic/main.go b/cmd/nginx-ingress/main.go similarity index 94% rename from cmd/nginx-ic/main.go rename to cmd/nginx-ingress/main.go index 2ae44e662e..a5c3b33cf4 100644 --- a/cmd/nginx-ic/main.go +++ b/cmd/nginx-ingress/main.go @@ -230,19 +230,19 @@ func main() { controllerNamespace := os.Getenv("POD_NAMESPACE") lbcInput := controller.NewLoadBalancerControllerInput{ - KubeClient: kubeClient, - ResyncPeriod: 30 * time.Second, - Namespace: *watchNamespace, - CNF: cnf, - NginxConfigMaps: *nginxConfigMaps, - DefaultServerSecret: *defaultServerSecret, - NginxPlus: *nginxPlus, - IngressClass: *ingressClass, - UseIngressClassOnly: *useIngressClassOnly, - ExternalServiceName: *externalService, - ControllerNamespace: controllerNamespace, - ReportIngressStatus: *reportIngressStatus, - LeaderElectionEnabled: *leaderElectionEnabled, + KubeClient: kubeClient, + ResyncPeriod: 30 * time.Second, + Namespace: *watchNamespace, + NginxConfigurator: cnf, + NginxConfigMaps: *nginxConfigMaps, + DefaultServerSecret: *defaultServerSecret, + IsNginxPlus: *nginxPlus, + IngressClass: *ingressClass, + UseIngressClassOnly: *useIngressClassOnly, + ExternalServiceName: *externalService, + ControllerNamespace: controllerNamespace, + ReportIngressStatus: *reportIngressStatus, + IsLeaderElectionEnabled: *leaderElectionEnabled, } lbc := controller.NewLoadBalancerController(lbcInput) go handleTermination(lbc, ngxc, nginxDone) diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 9fe5372f4b..09a9a0c7a9 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -49,63 +49,63 @@ const ( // LoadBalancerController watches Kubernetes API and // reconfigures NGINX via NginxController when needed type LoadBalancerController struct { - client kubernetes.Interface - ingController cache.Controller - svcController cache.Controller - endpController cache.Controller - cfgmController cache.Controller - secrController cache.Controller - ingLister StoreToIngressLister - svcLister cache.Store - endpLister StoreToEndpointLister - cfgmLister StoreToConfigMapLister - secrLister StoreToSecretLister - syncQueue *taskQueue - stopCh chan struct{} - cnf *nginx.Configurator - watchNginxConfigMaps bool - nginxPlus bool - recorder record.EventRecorder - defaultServerSecret string - ingressClass string - useIngressClassOnly bool - statusUpdater *StatusUpdater - leaderElector *leaderelection.LeaderElector - reportIngressStatus bool - leaderElectionEnabled bool + client kubernetes.Interface + ingressController cache.Controller + svcController cache.Controller + endpointController cache.Controller + configMapController cache.Controller + secretController cache.Controller + ingressLister StoreToIngressLister + svcLister cache.Store + endpointLister StoreToEndpointLister + configMapLister StoreToConfigMapLister + secretLister StoreToSecretLister + syncQueue *TaskQueue + stop chan struct{} + configurator *nginx.Configurator + watchNginxConfigMaps bool + isNginxPlus bool + recorder record.EventRecorder + defaultServerSecret string + ingressClass string + useIngressClassOnly bool + statusUpdater *StatusUpdater + leaderElector *leaderelection.LeaderElector + reportIngressStatus bool + isLeaderElectionEnabled bool } var keyFunc = cache.DeletionHandlingMetaNamespaceKeyFunc // NewLoadBalancerControllerInput holds the input needed to call NewLoadBalancerController. type NewLoadBalancerControllerInput struct { - KubeClient kubernetes.Interface - ResyncPeriod time.Duration - Namespace string - CNF *nginx.Configurator - NginxConfigMaps string - DefaultServerSecret string - NginxPlus bool - IngressClass string - UseIngressClassOnly bool - ExternalServiceName string - ControllerNamespace string - ReportIngressStatus bool - LeaderElectionEnabled bool + KubeClient kubernetes.Interface + ResyncPeriod time.Duration + Namespace string + NginxConfigurator *nginx.Configurator + NginxConfigMaps string + DefaultServerSecret string + IsNginxPlus bool + IngressClass string + UseIngressClassOnly bool + ExternalServiceName string + ControllerNamespace string + ReportIngressStatus bool + IsLeaderElectionEnabled bool } // NewLoadBalancerController creates a controller func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalancerController { lbc := LoadBalancerController{ - client: input.KubeClient, - stopCh: make(chan struct{}), - cnf: input.CNF, - defaultServerSecret: input.DefaultServerSecret, - nginxPlus: input.NginxPlus, - ingressClass: input.IngressClass, - useIngressClassOnly: input.UseIngressClassOnly, - reportIngressStatus: input.ReportIngressStatus, - leaderElectionEnabled: input.LeaderElectionEnabled, + client: input.KubeClient, + stop: make(chan struct{}), + configurator: input.NginxConfigurator, + defaultServerSecret: input.DefaultServerSecret, + isNginxPlus: input.IsNginxPlus, + ingressClass: input.IngressClass, + useIngressClassOnly: input.UseIngressClassOnly, + reportIngressStatus: input.ReportIngressStatus, + isLeaderElectionEnabled: input.IsLeaderElectionEnabled, } eventBroadcaster := record.NewBroadcaster() @@ -120,205 +120,199 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc glog.V(3).Infof("Nginx Ingress Controller has class: %v", input.IngressClass) - ingHandlers := cache.ResourceEventHandlerFuncs{ + ingressHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { - addIng := obj.(*extensions.Ingress) - if !lbc.isNginxIngress(addIng) { - glog.Infof("Ignoring Ingress %v based on Annotation %v", addIng.Name, ingressClassKey) + ingress := obj.(*extensions.Ingress) + if !lbc.isNginxIngress(ingress) { + glog.Infof("Ignoring Ingress %v based on Annotation %v", ingress.Name, ingressClassKey) return } - glog.V(3).Infof("Adding Ingress: %v", addIng.Name) + glog.V(3).Infof("Adding Ingress: %v", ingress.Name) lbc.syncQueue.enqueue(obj) }, DeleteFunc: func(obj interface{}) { - remIng, isIng := obj.(*extensions.Ingress) + ingress, isIng := obj.(*extensions.Ingress) if !isIng { deletedState, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { glog.V(3).Infof("Error received unexpected object: %v", obj) return } - remIng, ok = deletedState.Obj.(*extensions.Ingress) + ingress, ok = deletedState.Obj.(*extensions.Ingress) if !ok { glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Ingress object: %v", deletedState.Obj) return } } - if !lbc.isNginxIngress(remIng) { + if !lbc.isNginxIngress(ingress) { return } - if isMinion(remIng) { - master, err := lbc.findMasterForMinion(remIng) + if isMinion(ingress) { + master, err := lbc.findMasterForMinion(ingress) if err != nil { - glog.Infof("Ignoring Ingress %v(Minion): %v", remIng.Name, err) + glog.Infof("Ignoring Ingress %v(Minion): %v", ingress.Name, err) return } - glog.V(3).Infof("Removing Ingress: %v(Minion) for %v(Master)", remIng.Name, master.Name) + glog.V(3).Infof("Removing Ingress: %v(Minion) for %v(Master)", ingress.Name, master.Name) lbc.syncQueue.enqueue(master) } else { - glog.V(3).Infof("Removing Ingress: %v", remIng.Name) + glog.V(3).Infof("Removing Ingress: %v", ingress.Name) lbc.syncQueue.enqueue(obj) } }, - UpdateFunc: func(old, cur interface{}) { - curIng := cur.(*extensions.Ingress) - oldIng := old.(*extensions.Ingress) - if !lbc.isNginxIngress(curIng) { + UpdateFunc: func(old, current interface{}) { + c := current.(*extensions.Ingress) + o := old.(*extensions.Ingress) + if !lbc.isNginxIngress(c) { return } - if hasChanges(oldIng, curIng) { - glog.V(3).Infof("Ingress %v changed, syncing", curIng.Name) - lbc.syncQueue.enqueue(cur) + if hasChanges(o, c) { + glog.V(3).Infof("Ingress %v changed, syncing", c.Name) + lbc.syncQueue.enqueue(c) } }, } - lbc.ingLister.Store, lbc.ingController = cache.NewInformer( - cache.NewListWatchFromClient(lbc.client.Extensions().RESTClient(), "ingresses", input.Namespace, fields.Everything()), - &extensions.Ingress{}, input.ResyncPeriod, ingHandlers) - - // statusUpdater requires ingLister to be instantiated, above. - lbc.statusUpdater = &StatusUpdater{ - client: input.KubeClient, - namespace: input.ControllerNamespace, - externalServiceName: input.ExternalServiceName, - ingLister: &lbc.ingLister, - keyFunc: keyFunc, - } - - if input.ReportIngressStatus && input.LeaderElectionEnabled { - leaderCallbacks := leaderelection.LeaderCallbacks{ - OnStartedLeading: func(stop <-chan struct{}) { - glog.V(3).Info("started leading, updating ingress status") - ingresses, mergeableIngresses := lbc.getManagedIngresses() - err := lbc.statusUpdater.UpdateManagedAndMergeableIngresses(ingresses, mergeableIngresses) - if err != nil { - glog.V(3).Infof("error updating status when starting leading: %v", err) - } - }, - } - var err error - lbc.leaderElector, err = NewLeaderElector(input.KubeClient, leaderCallbacks, input.ControllerNamespace) - if err != nil { - glog.V(3).Infof("Error starting LeaderElection: %v", err) - } - } + lbc.ingressLister.Store, lbc.ingressController = cache.NewInformer( + cache.NewListWatchFromClient( + lbc.client.Extensions().RESTClient(), + "ingresses", + input.Namespace, + fields.Everything()), + &extensions.Ingress{}, + input.ResyncPeriod, + ingressHandlers, + ) svcHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { - addSvc := obj.(*api_v1.Service) - if lbc.isExternalServiceForStatus(addSvc) { - lbc.syncQueue.enqueue(addSvc) + svc := obj.(*api_v1.Service) + if lbc.isExternalServiceForStatus(svc) { + lbc.syncQueue.enqueue(svc) return } - glog.V(3).Infof("Adding service: %v", addSvc.Name) - lbc.enqueueIngressForService(addSvc) + glog.V(3).Infof("Adding service: %v", svc.Name) + lbc.enqueueIngressForService(svc) }, DeleteFunc: func(obj interface{}) { - remSvc, isSvc := obj.(*api_v1.Service) + svc, isSvc := obj.(*api_v1.Service) if !isSvc { deletedState, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { glog.V(3).Infof("Error received unexpected object: %v", obj) return } - remSvc, ok = deletedState.Obj.(*api_v1.Service) + svc, ok = deletedState.Obj.(*api_v1.Service) if !ok { glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Service object: %v", deletedState.Obj) return } } - if lbc.isExternalServiceForStatus(remSvc) { - lbc.syncQueue.enqueue(remSvc) + if lbc.isExternalServiceForStatus(svc) { + lbc.syncQueue.enqueue(svc) return } - glog.V(3).Infof("Removing service: %v", remSvc.Name) - lbc.enqueueIngressForService(remSvc) + glog.V(3).Infof("Removing service: %v", svc.Name) + lbc.enqueueIngressForService(svc) }, UpdateFunc: func(old, cur interface{}) { if !reflect.DeepEqual(old, cur) { - curSvc := cur.(*api_v1.Service) - if lbc.isExternalServiceForStatus(curSvc) { - lbc.syncQueue.enqueue(curSvc) + svc := cur.(*api_v1.Service) + if lbc.isExternalServiceForStatus(svc) { + lbc.syncQueue.enqueue(svc) return } - glog.V(3).Infof("Service %v changed, syncing", curSvc.Name) - lbc.enqueueIngressForService(curSvc) + glog.V(3).Infof("Service %v changed, syncing", svc.Name) + lbc.enqueueIngressForService(svc) } }, } lbc.svcLister, lbc.svcController = cache.NewInformer( - cache.NewListWatchFromClient(lbc.client.Core().RESTClient(), "services", input.Namespace, fields.Everything()), - &api_v1.Service{}, input.ResyncPeriod, svcHandlers) - - endpHandlers := cache.ResourceEventHandlerFuncs{ + cache.NewListWatchFromClient( + lbc.client.Core().RESTClient(), + "services", + input.Namespace, + fields.Everything()), + &api_v1.Service{}, + input.ResyncPeriod, + svcHandlers, + ) + + endpointHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { - addEndp := obj.(*api_v1.Endpoints) - glog.V(3).Infof("Adding endpoints: %v", addEndp.Name) + endpoint := obj.(*api_v1.Endpoints) + glog.V(3).Infof("Adding endpoints: %v", endpoint.Name) lbc.syncQueue.enqueue(obj) }, DeleteFunc: func(obj interface{}) { - remEndp, isEndp := obj.(*api_v1.Endpoints) - if !isEndp { + endpoint, isEndpoint := obj.(*api_v1.Endpoints) + if !isEndpoint { deletedState, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { glog.V(3).Infof("Error received unexpected object: %v", obj) return } - remEndp, ok = deletedState.Obj.(*api_v1.Endpoints) + endpoint, ok = deletedState.Obj.(*api_v1.Endpoints) if !ok { glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Endpoints object: %v", deletedState.Obj) return } } - glog.V(3).Infof("Removing endpoints: %v", remEndp.Name) + glog.V(3).Infof("Removing endpoints: %v", endpoint.Name) lbc.syncQueue.enqueue(obj) }, UpdateFunc: func(old, cur interface{}) { if !reflect.DeepEqual(old, cur) { - glog.V(3).Infof("Endpoints %v changed, syncing", - cur.(*api_v1.Endpoints).Name) + glog.V(3).Infof("Endpoints %v changed, syncing", cur.(*api_v1.Endpoints).Name) lbc.syncQueue.enqueue(cur) } }, } - lbc.endpLister.Store, lbc.endpController = cache.NewInformer( - cache.NewListWatchFromClient(lbc.client.Core().RESTClient(), "endpoints", input.Namespace, fields.Everything()), - &api_v1.Endpoints{}, input.ResyncPeriod, endpHandlers) - secrHandlers := cache.ResourceEventHandlerFuncs{ + lbc.endpointLister.Store, lbc.endpointController = cache.NewInformer( + cache.NewListWatchFromClient( + lbc.client.Core().RESTClient(), + "endpoints", + input.Namespace, + fields.Everything()), + &api_v1.Endpoints{}, + input.ResyncPeriod, + endpointHandlers, + ) + + secretHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { - secr := obj.(*api_v1.Secret) - if err := lbc.ValidateSecret(secr); err != nil { + secret := obj.(*api_v1.Secret) + if err := lbc.ValidateSecret(secret); err != nil { return } - nsname := secr.Namespace + "/" + secr.Name + nsname := secret.Namespace + "/" + secret.Name if nsname == lbc.defaultServerSecret { - glog.V(3).Infof("Adding default server Secret: %v", secr.Name) + glog.V(3).Infof("Adding default server Secret: %v", secret.Name) lbc.syncQueue.enqueue(obj) } }, DeleteFunc: func(obj interface{}) { - remSecr, isSecr := obj.(*api_v1.Secret) + secret, isSecr := obj.(*api_v1.Secret) if !isSecr { deletedState, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { glog.V(3).Infof("Error received unexpected object: %v", obj) return } - remSecr, ok = deletedState.Obj.(*api_v1.Secret) + secret, ok = deletedState.Obj.(*api_v1.Secret) if !ok { glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Secret object: %v", deletedState.Obj) return } } - if err := lbc.ValidateSecret(remSecr); err != nil { + if err := lbc.ValidateSecret(secret); err != nil { return } - glog.V(3).Infof("Removing Secret: %v", remSecr.Name) + glog.V(3).Infof("Removing Secret: %v", secret.Name) lbc.syncQueue.enqueue(obj) }, UpdateFunc: func(old, cur interface{}) { @@ -329,16 +323,22 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc } if !reflect.DeepEqual(old, cur) { - glog.V(3).Infof("Secret %v changed, syncing", - cur.(*api_v1.Secret).Name) + glog.V(3).Infof("Secret %v changed, syncing", cur.(*api_v1.Secret).Name) lbc.syncQueue.enqueue(cur) } }, } - lbc.secrLister.Store, lbc.secrController = cache.NewInformer( - cache.NewListWatchFromClient(lbc.client.Core().RESTClient(), "secrets", input.Namespace, fields.Everything()), - &api_v1.Secret{}, input.ResyncPeriod, secrHandlers) + lbc.secretLister.Store, lbc.secretController = cache.NewInformer( + cache.NewListWatchFromClient( + lbc.client.Core().RESTClient(), + "secrets", + input.Namespace, + fields.Everything()), + &api_v1.Secret{}, + input.ResyncPeriod, + secretHandlers, + ) if input.NginxConfigMaps != "" { nginxConfigMapsNS, nginxConfigMapsName, err := ParseNamespaceName(input.NginxConfigMaps) @@ -347,47 +347,82 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc } else { lbc.watchNginxConfigMaps = true - cfgmHandlers := cache.ResourceEventHandlerFuncs{ + configMapHandlers := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { - cfgm := obj.(*api_v1.ConfigMap) - if cfgm.Name == nginxConfigMapsName { - glog.V(3).Infof("Adding ConfigMap: %v", cfgm.Name) + configMap := obj.(*api_v1.ConfigMap) + if configMap.Name == nginxConfigMapsName { + glog.V(3).Infof("Adding ConfigMap: %v", configMap.Name) lbc.syncQueue.enqueue(obj) } }, DeleteFunc: func(obj interface{}) { - cfgm, isCfgm := obj.(*api_v1.ConfigMap) - if !isCfgm { + configMap, isConfigMap := obj.(*api_v1.ConfigMap) + if !isConfigMap { deletedState, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { glog.V(3).Infof("Error received unexpected object: %v", obj) return } - cfgm, ok = deletedState.Obj.(*api_v1.ConfigMap) + configMap, ok = deletedState.Obj.(*api_v1.ConfigMap) if !ok { glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-ConfigMap object: %v", deletedState.Obj) return } } - if cfgm.Name == nginxConfigMapsName { - glog.V(3).Infof("Removing ConfigMap: %v", cfgm.Name) + if configMap.Name == nginxConfigMapsName { + glog.V(3).Infof("Removing ConfigMap: %v", configMap.Name) lbc.syncQueue.enqueue(obj) } }, UpdateFunc: func(old, cur interface{}) { if !reflect.DeepEqual(old, cur) { - cfgm := cur.(*api_v1.ConfigMap) - if cfgm.Name == nginxConfigMapsName { - glog.V(3).Infof("ConfigMap %v changed, syncing", - cur.(*api_v1.ConfigMap).Name) + configMap := cur.(*api_v1.ConfigMap) + if configMap.Name == nginxConfigMapsName { + glog.V(3).Infof("ConfigMap %v changed, syncing", cur.(*api_v1.ConfigMap).Name) lbc.syncQueue.enqueue(cur) } } }, } - lbc.cfgmLister.Store, lbc.cfgmController = cache.NewInformer( - cache.NewListWatchFromClient(lbc.client.Core().RESTClient(), "configmaps", nginxConfigMapsNS, fields.Everything()), - &api_v1.ConfigMap{}, input.ResyncPeriod, cfgmHandlers) + + lbc.configMapLister.Store, lbc.configMapController = cache.NewInformer( + cache.NewListWatchFromClient( + lbc.client.Core().RESTClient(), + "configmaps", + nginxConfigMapsNS, + fields.Everything()), + &api_v1.ConfigMap{}, + input.ResyncPeriod, + configMapHandlers, + ) + } + } + + // statusUpdater requires ingLister to be instantiated, above. + lbc.statusUpdater = &StatusUpdater{ + client: input.KubeClient, + namespace: input.ControllerNamespace, + externalServiceName: input.ExternalServiceName, + ingLister: &lbc.ingressLister, + keyFunc: keyFunc, + } + + if input.ReportIngressStatus && input.IsLeaderElectionEnabled { + leaderCallbacks := leaderelection.LeaderCallbacks{ + OnStartedLeading: func(stop <-chan struct{}) { + glog.V(3).Info("started leading, updating ingress status") + ingresses, mergeableIngresses := lbc.getManagedIngresses() + err := lbc.statusUpdater.UpdateManagedAndMergeableIngresses(ingresses, mergeableIngresses) + if err != nil { + glog.V(3).Infof("error updating status when starting leading: %v", err) + } + }, + } + + var err error + lbc.leaderElector, err = NewLeaderElector(input.KubeClient, leaderCallbacks, input.ControllerNamespace) + if err != nil { + glog.V(3).Infof("Error starting LeaderElection: %v", err) } } @@ -395,10 +430,10 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc } // hasChanges ignores Status or ResourceVersion changes -func hasChanges(oldIng *extensions.Ingress, curIng *extensions.Ingress) bool { - oldIng.Status.LoadBalancer.Ingress = curIng.Status.LoadBalancer.Ingress - oldIng.ResourceVersion = curIng.ResourceVersion - return !reflect.DeepEqual(oldIng, curIng) +func hasChanges(old *extensions.Ingress, current *extensions.Ingress) bool { + old.Status.LoadBalancer.Ingress = current.Status.LoadBalancer.Ingress + old.ResourceVersion = current.ResourceVersion + return !reflect.DeepEqual(old, current) } // Run starts the loadbalancer controller @@ -406,29 +441,29 @@ func (lbc *LoadBalancerController) Run() { if lbc.leaderElector != nil { go lbc.leaderElector.Run() } - go lbc.svcController.Run(lbc.stopCh) - go lbc.endpController.Run(lbc.stopCh) - go lbc.secrController.Run(lbc.stopCh) + go lbc.svcController.Run(lbc.stop) + go lbc.endpointController.Run(lbc.stop) + go lbc.secretController.Run(lbc.stop) if lbc.watchNginxConfigMaps { - go lbc.cfgmController.Run(lbc.stopCh) + go lbc.configMapController.Run(lbc.stop) } - go lbc.ingController.Run(lbc.stopCh) - go lbc.syncQueue.run(time.Second, lbc.stopCh) - <-lbc.stopCh + go lbc.ingressController.Run(lbc.stop) + go lbc.syncQueue.run(time.Second, lbc.stop) + <-lbc.stop } // Stop shutdowns the load balancer controller func (lbc *LoadBalancerController) Stop() { - close(lbc.stopCh) + close(lbc.stop) lbc.syncQueue.shutdown() } -func (lbc *LoadBalancerController) syncEndp(task Task) { +func (lbc *LoadBalancerController) syncEndpoint(task Task) { key := task.Key glog.V(3).Infof("Syncing endpoints %v", key) - obj, endpExists, err := lbc.endpLister.GetByKey(key) + obj, endpExists, err := lbc.endpointLister.GetByKey(key) if err != nil { lbc.syncQueue.requeue(task, err) return @@ -447,7 +482,7 @@ func (lbc *LoadBalancerController) syncEndp(task Task) { glog.Errorf("Ignoring Ingress %v(Minion): %v", ing.Name, err) continue } - if !lbc.cnf.HasIngress(master) { + if !lbc.configurator.HasIngress(master) { continue } mergeableIngresses, err := lbc.createMergableIngresses(master) @@ -457,13 +492,13 @@ func (lbc *LoadBalancerController) syncEndp(task Task) { } glog.V(3).Infof("Updating Endpoints for %v/%v", ing.Namespace, ing.Name) - err = lbc.cnf.UpdateEndpointsMergeableIngress(mergeableIngresses) + err = lbc.configurator.UpdateEndpointsMergeableIngress(mergeableIngresses) if err != nil { glog.Errorf("Error updating endpoints for %v/%v: %v", ing.Namespace, ing.Name, err) } continue } - if !lbc.cnf.HasIngress(&ing) { + if !lbc.configurator.HasIngress(&ing) { continue } ingEx, err := lbc.createIngress(&ing) @@ -472,7 +507,7 @@ func (lbc *LoadBalancerController) syncEndp(task Task) { continue } glog.V(3).Infof("Updating Endpoints for %v/%v", ing.Namespace, ing.Name) - err = lbc.cnf.UpdateEndpoints(ingEx) + err = lbc.configurator.UpdateEndpoints(ingEx) if err != nil { glog.Errorf("Error updating endpoints for %v/%v: %v", ing.Namespace, ing.Name, err) } @@ -480,20 +515,20 @@ func (lbc *LoadBalancerController) syncEndp(task Task) { } } -func (lbc *LoadBalancerController) syncCfgm(task Task) { +func (lbc *LoadBalancerController) syncConfig(task Task) { key := task.Key glog.V(3).Infof("Syncing configmap %v", key) - obj, cfgmExists, err := lbc.cfgmLister.GetByKey(key) + obj, configExists, err := lbc.configMapLister.GetByKey(key) if err != nil { lbc.syncQueue.requeue(task, err) return } cfg := nginx.NewDefaultConfig() - if cfgmExists { + if configExists { cfgm := obj.(*api_v1.ConfigMap) - cfg = nginx.ParseConfigMap(cfgm, lbc.nginxPlus) + cfg = nginx.ParseConfigMap(cfgm, lbc.isNginxPlus) lbc.statusUpdater.SaveStatusFromExternalStatus(cfgm.Data["external-status-address"]) } @@ -508,38 +543,31 @@ func (lbc *LoadBalancerController) syncCfgm(task Task) { } } - if err := lbc.cnf.UpdateConfig(cfg, ingExes, mergeableIngresses); err != nil { - if cfgmExists { - cfgm := obj.(*api_v1.ConfigMap) - lbc.recorder.Eventf(cfgm, api_v1.EventTypeWarning, "UpdatedWithError", "Configuration from %v was updated, but not applied: %v", key, err) - } - for _, ingEx := range ingExes { - lbc.recorder.Eventf(ingEx.Ingress, api_v1.EventTypeWarning, "UpdatedWithError", "Configuration for %v/%v was updated, but not applied: %v", - ingEx.Ingress.Namespace, ingEx.Ingress.Name, err) - } - for _, mergeableIng := range mergeableIngresses { - master := mergeableIng.Master - lbc.recorder.Eventf(master.Ingress, api_v1.EventTypeWarning, "UpdatedWithError", "Configuration for %v/%v(Master) was updated, but not applied: %v", - master.Ingress.Namespace, master.Ingress.Name, err) - for _, minion := range mergeableIng.Minions { - lbc.recorder.Eventf(minion.Ingress, api_v1.EventTypeWarning, "UpdatedWithError", "Configuration for %v/%v(Minion) was updated, but not applied: %v", - minion.Ingress.Namespace, minion.Ingress.Name, err) - } - } - } else { - if cfgmExists { - cfgm := obj.(*api_v1.ConfigMap) - lbc.recorder.Eventf(cfgm, api_v1.EventTypeNormal, "Updated", "Configuration from %v was updated", key) - } - for _, ingEx := range ingExes { - lbc.recorder.Eventf(ingEx.Ingress, api_v1.EventTypeNormal, "Updated", "Configuration for %v/%v was updated", ingEx.Ingress.Namespace, ingEx.Ingress.Name) - } - for _, mergeableIng := range mergeableIngresses { - master := mergeableIng.Master - lbc.recorder.Eventf(master.Ingress, api_v1.EventTypeWarning, "Updated", "Configuration for %v/%v(Master) was updated", master.Ingress.Namespace, master.Ingress.Name) - for _, minion := range mergeableIng.Minions { - lbc.recorder.Eventf(minion.Ingress, api_v1.EventTypeWarning, "Updated", "Configuration for %v/%v(Minion) was updated", minion.Ingress.Namespace, minion.Ingress.Name) - } + updateErr := lbc.configurator.UpdateConfig(cfg, ingExes, mergeableIngresses) + + eventTitle := "Updated" + eventType := api_v1.EventTypeNormal + eventWarningMessage := "" + + if updateErr != nil { + eventTitle = "UpdatedWithError" + eventType = api_v1.EventTypeWarning + eventWarningMessage = "but was not applied" + } + if configExists { + cfgm := obj.(*api_v1.ConfigMap) + lbc.recorder.Eventf(cfgm, eventType, eventTitle, "Configuration from %v was updated %s: %v", key, eventWarningMessage, err) + } + for _, ingEx := range ingExes { + lbc.recorder.Eventf(ingEx.Ingress, eventType, eventTitle, "Configuration for %v/%v was updated %s: %v", + ingEx.Ingress.Namespace, ingEx.Ingress.Name, eventWarningMessage, err) + } + for _, mergeableIng := range mergeableIngresses { + master := mergeableIng.Master + lbc.recorder.Eventf(master.Ingress, eventType, eventTitle, "Configuration for %v/%v(Master) was updated %s: %v", master.Ingress.Namespace, master.Ingress.Name, eventWarningMessage, err) + for _, minion := range mergeableIng.Minions { + lbc.recorder.Eventf(minion.Ingress, eventType, eventTitle, "Configuration for %v/%v(Minion) was updated %s: %v", + minion.Ingress.Namespace, minion.Ingress.Name, eventWarningMessage, err) } } } @@ -548,7 +576,7 @@ func (lbc *LoadBalancerController) syncCfgm(task Task) { func (lbc *LoadBalancerController) getManagedIngresses() ([]extensions.Ingress, map[string]*nginx.MergeableIngresses) { mergeableIngresses := make(map[string]*nginx.MergeableIngresses) var managedIngresses []extensions.Ingress - ings, _ := lbc.ingLister.List() + ings, _ := lbc.ingressLister.List() for i := range ings.Items { ing := ings.Items[i] if !lbc.isNginxIngress(&ing) { @@ -560,7 +588,7 @@ func (lbc *LoadBalancerController) getManagedIngresses() ([]extensions.Ingress, glog.Errorf("Ignoring Ingress %v(Minion): %v", ing, err) continue } - if !lbc.cnf.HasIngress(master) { + if !lbc.configurator.HasIngress(master) { continue } if _, exists := mergeableIngresses[master.Name]; !exists { @@ -573,7 +601,7 @@ func (lbc *LoadBalancerController) getManagedIngresses() ([]extensions.Ingress, } continue } - if !lbc.cnf.HasIngress(&ing) { + if !lbc.configurator.HasIngress(&ing) { continue } managedIngresses = append(managedIngresses, ing) @@ -602,10 +630,10 @@ func (lbc *LoadBalancerController) sync(task Task) { case IngressMinion: lbc.syncIngMinion(task) case ConfigMap: - lbc.syncCfgm(task) + lbc.syncConfig(task) return case Endpoints: - lbc.syncEndp(task) + lbc.syncEndpoint(task) return case Secret: lbc.syncSecret(task) @@ -617,7 +645,7 @@ func (lbc *LoadBalancerController) sync(task Task) { func (lbc *LoadBalancerController) syncIngMinion(task Task) { key := task.Key - obj, ingExists, err := lbc.ingLister.Store.GetByKey(key) + obj, ingExists, err := lbc.ingressLister.Store.GetByKey(key) if err != nil { lbc.syncQueue.requeue(task, err) return @@ -640,7 +668,7 @@ func (lbc *LoadBalancerController) syncIngMinion(task Task) { _, err = lbc.createIngress(minion) if err != nil { lbc.syncQueue.requeueAfter(task, err, 5*time.Second) - if !lbc.cnf.HasMinion(master, minion) { + if !lbc.configurator.HasMinion(master, minion) { return } } @@ -650,7 +678,7 @@ func (lbc *LoadBalancerController) syncIngMinion(task Task) { func (lbc *LoadBalancerController) syncIng(task Task) { key := task.Key - ing, ingExists, err := lbc.ingLister.GetByKeySafe(key) + ing, ingExists, err := lbc.ingressLister.GetByKeySafe(key) if err != nil { lbc.syncQueue.requeue(task, err) return @@ -659,7 +687,7 @@ func (lbc *LoadBalancerController) syncIng(task Task) { if !ingExists { glog.V(2).Infof("Deleting Ingress: %v\n", key) - err := lbc.cnf.DeleteIngress(key) + err := lbc.configurator.DeleteIngress(key) if err != nil { glog.Errorf("Error when deleting configuration for %v: %v", key, err) } @@ -679,22 +707,27 @@ func (lbc *LoadBalancerController) syncIng(task Task) { } return } - err = lbc.cnf.AddOrUpdateMergeableIngress(mergeableIngExs) - if err != nil { - lbc.recorder.Eventf(ing, api_v1.EventTypeWarning, "AddedOrUpdatedWithError", "Configuration for %v(Master) was added or updated, but not applied: %v", key, err) - for _, minion := range mergeableIngExs.Minions { - lbc.recorder.Eventf(ing, api_v1.EventTypeWarning, "AddedOrUpdatedWithError", "Configuration for %v/%v(Minion) was added or updated, but not applied: %v", minion.Ingress.Namespace, minion.Ingress.Name, err) - } - } else { - lbc.recorder.Eventf(ing, api_v1.EventTypeNormal, "AddedOrUpdated", "Configuration for %v(Master) was added or updated", key) - for _, minion := range mergeableIngExs.Minions { - lbc.recorder.Eventf(ing, api_v1.EventTypeNormal, "AddedOrUpdated", "Configuration for %v/%v(Minion) was added or updated", minion.Ingress.Namespace, minion.Ingress.Name) - } + addErr := lbc.configurator.AddOrUpdateMergeableIngress(mergeableIngExs) + + // record correct eventType and message depending on the error + eventTitle := "AddedOrUpdated" + eventType := api_v1.EventTypeNormal + eventWarningMessage := "" + + if addErr != nil { + eventTitle = "AddedOrUpdatedWithError" + eventType = api_v1.EventTypeWarning + eventWarningMessage = "but was not applied" + } + lbc.recorder.Eventf(ing, eventType, eventTitle, "Configuration for %v(Master) was added or updated %s: %v", key, eventWarningMessage, err) + for _, minion := range mergeableIngExs.Minions { + lbc.recorder.Eventf(ing, eventType, eventTitle, "Configuration for %v/%v(Minion) was added or updated %s: %v", minion.Ingress.Namespace, minion.Ingress.Name, eventWarningMessage, err) } + if lbc.reportStatusEnabled() { err = lbc.statusUpdater.UpdateMergableIngresses(mergeableIngExs) if err != nil { - glog.V(3).Infof("error updating ing status: %v", err) + glog.V(3).Infof("error updating ingress status: %v", err) } } return @@ -712,7 +745,7 @@ func (lbc *LoadBalancerController) syncIng(task Task) { return } - err = lbc.cnf.AddOrUpdateIngress(ingEx) + err = lbc.configurator.AddOrUpdateIngress(ingEx) if err != nil { lbc.recorder.Eventf(ing, api_v1.EventTypeWarning, "AddedOrUpdatedWithError", "Configuration for %v was added or updated, but not applied: %v", key, err) } else { @@ -760,7 +793,7 @@ func (lbc *LoadBalancerController) isExternalServiceForStatus(svc *api_v1.Servic // reportStatusEnabled determines if we should attempt to report status func (lbc *LoadBalancerController) reportStatusEnabled() bool { if lbc.reportIngressStatus { - if lbc.leaderElectionEnabled { + if lbc.isLeaderElectionEnabled { return lbc.leaderElector != nil && lbc.leaderElector.IsLeader() } return true @@ -770,7 +803,7 @@ func (lbc *LoadBalancerController) reportStatusEnabled() bool { func (lbc *LoadBalancerController) syncSecret(task Task) { key := task.Key - obj, secrExists, err := lbc.secrLister.Store.GetByKey(key) + obj, secrExists, err := lbc.secretLister.Store.GetByKey(key) if err != nil { lbc.syncQueue.requeue(task, err) return @@ -804,7 +837,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { glog.Errorf("Ignoring Ingress %v(Minion): %v", minion.Name, err) continue } - err = lbc.cnf.AddOrUpdateMergeableIngress(mergeableIngress) + err = lbc.configurator.AddOrUpdateMergeableIngress(mergeableIngress) if err != nil { glog.Errorf("Failed to update Ingress %v(Master) of %v(Minion): %v", master.Name, minion.Name, err) } @@ -813,7 +846,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { lbc.syncQueue.enqueue(&minion) } - if err := lbc.cnf.DeleteSecret(key, nonMinions); err != nil { + if err := lbc.configurator.DeleteSecret(key, nonMinions); err != nil { glog.Errorf("Error when deleting Secret: %v: %v", key, err) } @@ -836,7 +869,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { glog.Errorf("Couldn't validate the default server Secret %v: %v", key, err) lbc.recorder.Eventf(secret, api_v1.EventTypeWarning, "Rejected", "the default server Secret %v was rejected, using the previous version: %v", key, err) } else { - err := lbc.cnf.AddOrUpdateDefaultServerTLSSecret(secret) + err := lbc.configurator.AddOrUpdateDefaultServerTLSSecret(secret) if err != nil { glog.Errorf("Error when updating the default server Secret %v: %v", key, err) lbc.recorder.Eventf(secret, api_v1.EventTypeWarning, "UpdatedWithError", "the default server Secret %v was updated, but not applied: %v", key, err) @@ -864,7 +897,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { glog.Errorf("Ignoring Ingress %v(Minion): %v", minion.Name, err) continue } - err = lbc.cnf.AddOrUpdateMergeableIngress(mergeableIngress) + err = lbc.configurator.AddOrUpdateMergeableIngress(mergeableIngress) if err != nil { glog.Errorf("Failed to update Ingress %v(Master) of %v(Minion): %v", master.Name, minion.Name, err) } @@ -873,7 +906,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { lbc.syncQueue.enqueue(&minion) } - if err := lbc.cnf.DeleteSecret(key, nonMinions); err != nil { + if err := lbc.configurator.DeleteSecret(key, nonMinions); err != nil { glog.Errorf("Error when deleting Secret: %v: %v", key, err) } for _, ing := range nonMinions { @@ -884,7 +917,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { return } - if err := lbc.cnf.AddOrUpdateSecret(secret); err != nil { + if err := lbc.configurator.AddOrUpdateSecret(secret); err != nil { glog.Errorf("Error when updating Secret %v: %v", key, err) lbc.recorder.Eventf(secret, api_v1.EventTypeWarning, "UpdatedWithError", "%v was updated, but not applied: %v", key, err) for _, ing := range nonMinions { @@ -919,7 +952,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { } func (lbc *LoadBalancerController) findIngressesForSecret(secretNamespace string, secretName string) (nonMinions []extensions.Ingress, minions []extensions.Ingress, error error) { - ings, err := lbc.ingLister.List() + ings, err := lbc.ingressLister.List() if err != nil { return nil, nil, fmt.Errorf("Couldn't get the list of Ingress resources: %v", err) } @@ -935,7 +968,7 @@ items: } if !isMinion(&ing) { - if !lbc.cnf.HasIngress(&ing) { + if !lbc.configurator.HasIngress(&ing) { continue } for _, tls := range ing.Spec.TLS { @@ -944,7 +977,7 @@ items: continue items } } - if lbc.nginxPlus { + if lbc.isNginxPlus { if jwtKey, exists := ing.Annotations[nginx.JWTKeyAnnotation]; exists { if jwtKey == secretName { nonMinions = append(nonMinions, ing) @@ -956,14 +989,14 @@ items: // we're dealing with a minion // minions can only have JWT secrets - if lbc.nginxPlus { + if lbc.isNginxPlus { master, err := lbc.findMasterForMinion(&ing) if err != nil { glog.Infof("Ignoring Ingress %v(Minion): %v", ing.Name, err) continue } - if !lbc.cnf.HasMinion(master, &ing) { + if !lbc.configurator.HasMinion(master, &ing) { continue } @@ -992,7 +1025,7 @@ func (lbc *LoadBalancerController) enqueueIngressForService(svc *api_v1.Service) } ing = *master } - if !lbc.cnf.HasIngress(&ing) { + if !lbc.configurator.HasIngress(&ing) { continue } lbc.syncQueue.enqueue(&ing) @@ -1001,7 +1034,7 @@ func (lbc *LoadBalancerController) enqueueIngressForService(svc *api_v1.Service) } func (lbc *LoadBalancerController) getIngressesForService(svc *api_v1.Service) []extensions.Ingress { - ings, err := lbc.ingLister.GetServiceIngress(svc) + ings, err := lbc.ingressLister.GetServiceIngress(svc) if err != nil { glog.V(3).Infof("ignoring service %v: %v", svc.Name, err) return nil @@ -1043,7 +1076,7 @@ func (lbc *LoadBalancerController) createIngress(ing *extensions.Ingress) (*ngin ingEx.TLSSecrets[secretName] = secret } - if lbc.nginxPlus { + if lbc.isNginxPlus { if jwtKey, exists := ingEx.Ingress.Annotations[nginx.JWTKeyAnnotation]; exists { secretName := jwtKey @@ -1072,7 +1105,7 @@ func (lbc *LoadBalancerController) createIngress(ing *extensions.Ingress) (*ngin } else { ingEx.Endpoints[ing.Spec.Backend.ServiceName+ing.Spec.Backend.ServicePort.String()] = endps } - if lbc.nginxPlus && lbc.isHealthCheckEnabled(ing) { + if lbc.isNginxPlus && lbc.isHealthCheckEnabled(ing) { healthCheck := lbc.getHealthChecksForIngressBackend(ing.Spec.Backend, ing.Namespace) if healthCheck != nil { ingEx.HealthChecks[ing.Spec.Backend.ServiceName+ing.Spec.Backend.ServicePort.String()] = healthCheck @@ -1098,7 +1131,7 @@ func (lbc *LoadBalancerController) createIngress(ing *extensions.Ingress) (*ngin } else { ingEx.Endpoints[path.Backend.ServiceName+path.Backend.ServicePort.String()] = endps } - if lbc.nginxPlus && lbc.isHealthCheckEnabled(ing) { + if lbc.isNginxPlus && lbc.isHealthCheckEnabled(ing) { // Pull active health checks from k8 api healthCheck := lbc.getHealthChecksForIngressBackend(&path.Backend, ing.Namespace) if healthCheck != nil { @@ -1180,7 +1213,7 @@ func (lbc *LoadBalancerController) getEndpointsForIngressBackend(backend *extens return nil, err } - endps, err := lbc.endpLister.GetServiceEndpoints(svc) + endps, err := lbc.endpointLister.GetServiceEndpoints(svc) if err != nil { glog.V(3).Infof("Error getting endpoints for service %s from the cache: %v", svc.Name, err) return nil, err @@ -1319,7 +1352,7 @@ func (lbc *LoadBalancerController) isHealthCheckEnabled(ing *extensions.Ingress) // For NGINX Plus, it also checks if the secret follows the JWK Secret format. func (lbc *LoadBalancerController) ValidateSecret(secret *api_v1.Secret) error { err1 := nginx.ValidateTLSSecret(secret) - if !lbc.nginxPlus { + if !lbc.isNginxPlus { return err1 } @@ -1334,7 +1367,7 @@ func (lbc *LoadBalancerController) ValidateSecret(secret *api_v1.Secret) error { // getMinionsForHost returns a list of all minion ingress resources for a given master func (lbc *LoadBalancerController) getMinionsForMaster(master *nginx.IngressEx) ([]*nginx.IngressEx, error) { - ings, err := lbc.ingLister.List() + ings, err := lbc.ingressLister.List() if err != nil { return []*nginx.IngressEx{}, err } @@ -1347,7 +1380,7 @@ func (lbc *LoadBalancerController) getMinionsForMaster(master *nginx.IngressEx) var minions []*nginx.IngressEx var minionPaths = make(map[string]*extensions.Ingress) - for i, _ := range ings.Items { + for i := range ings.Items { if !lbc.isNginxIngress(&ings.Items[i]) { continue } @@ -1396,16 +1429,16 @@ func (lbc *LoadBalancerController) getMinionsForMaster(master *nginx.IngressEx) // findMasterForHost returns a master for a given minion func (lbc *LoadBalancerController) findMasterForMinion(minion *extensions.Ingress) (*extensions.Ingress, error) { - ings, err := lbc.ingLister.List() + ings, err := lbc.ingressLister.List() if err != nil { return &extensions.Ingress{}, err } - for i, _ := range ings.Items { + for i := range ings.Items { if !lbc.isNginxIngress(&ings.Items[i]) { continue } - if !lbc.cnf.HasIngress(&ings.Items[i]) { + if !lbc.configurator.HasIngress(&ings.Items[i]) { continue } if !isMaster(&ings.Items[i]) { diff --git a/internal/controller/controller_test.go b/internal/controller/controller_test.go index 64f2697e9f..665c5db487 100644 --- a/internal/controller/controller_test.go +++ b/internal/controller/controller_test.go @@ -159,9 +159,9 @@ func TestIsNginxIngress(t *testing.T) { func TestCreateMergableIngresses(t *testing.T) { cafeMaster, coffeeMinion, teaMinion, lbc := getMergableDefaults() - lbc.ingLister.Add(&cafeMaster) - lbc.ingLister.Add(&coffeeMinion) - lbc.ingLister.Add(&teaMinion) + lbc.ingressLister.Add(&cafeMaster) + lbc.ingressLister.Add(&coffeeMinion) + lbc.ingressLister.Add(&teaMinion) mergeableIngresses, err := lbc.createMergableIngresses(&cafeMaster) if err != nil { @@ -220,7 +220,7 @@ func TestCreateMergableIngressesInvalidMaster(t *testing.T) { }, }, } - lbc.ingLister.Add(&cafeMaster) + lbc.ingressLister.Add(&cafeMaster) expected := fmt.Errorf("Ingress Resource %v/%v with the 'nginx.org/mergeable-ingress-type' annotation set to 'master' cannot contain Paths", cafeMaster.Namespace, cafeMaster.Name) _, err := lbc.createMergableIngresses(&cafeMaster) @@ -237,9 +237,9 @@ func TestFindMasterForMinion(t *testing.T) { Paths: []extensions.HTTPIngressPath{}, } - lbc.ingLister.Add(&cafeMaster) - lbc.ingLister.Add(&coffeeMinion) - lbc.ingLister.Add(&teaMinion) + lbc.ingressLister.Add(&cafeMaster) + lbc.ingressLister.Add(&coffeeMinion) + lbc.ingressLister.Add(&teaMinion) master, err := lbc.findMasterForMinion(&coffeeMinion) if err != nil { @@ -261,8 +261,8 @@ func TestFindMasterForMinion(t *testing.T) { func TestFindMasterForMinionNoMaster(t *testing.T) { _, coffeeMinion, teaMinion, lbc := getMergableDefaults() - lbc.ingLister.Add(&coffeeMinion) - lbc.ingLister.Add(&teaMinion) + lbc.ingressLister.Add(&coffeeMinion) + lbc.ingressLister.Add(&teaMinion) expected := fmt.Errorf("Could not find a Master for Minion: '%v/%v'", coffeeMinion.Namespace, coffeeMinion.Name) _, err := lbc.findMasterForMinion(&coffeeMinion) @@ -291,8 +291,8 @@ func TestFindMasterForMinionInvalidMinion(t *testing.T) { }, } - lbc.ingLister.Add(&cafeMaster) - lbc.ingLister.Add(&coffeeMinion) + lbc.ingressLister.Add(&cafeMaster) + lbc.ingressLister.Add(&coffeeMinion) master, err := lbc.findMasterForMinion(&coffeeMinion) if err != nil { @@ -311,9 +311,9 @@ func TestGetMinionsForMaster(t *testing.T) { Paths: []extensions.HTTPIngressPath{}, } - lbc.ingLister.Add(&cafeMaster) - lbc.ingLister.Add(&coffeeMinion) - lbc.ingLister.Add(&teaMinion) + lbc.ingressLister.Add(&cafeMaster) + lbc.ingressLister.Add(&coffeeMinion) + lbc.ingressLister.Add(&teaMinion) cafeMasterIngEx, err := lbc.createIngress(&cafeMaster) if err != nil { @@ -364,9 +364,9 @@ func TestGetMinionsForMasterInvalidMinion(t *testing.T) { }, } - lbc.ingLister.Add(&cafeMaster) - lbc.ingLister.Add(&coffeeMinion) - lbc.ingLister.Add(&teaMinion) + lbc.ingressLister.Add(&cafeMaster) + lbc.ingressLister.Add(&coffeeMinion) + lbc.ingressLister.Add(&teaMinion) cafeMasterIngEx, err := lbc.createIngress(&cafeMaster) if err != nil { @@ -421,9 +421,9 @@ func TestGetMinionsForMasterConflictingPaths(t *testing.T) { }, }) - lbc.ingLister.Add(&cafeMaster) - lbc.ingLister.Add(&coffeeMinion) - lbc.ingLister.Add(&teaMinion) + lbc.ingressLister.Add(&cafeMaster) + lbc.ingressLister.Add(&coffeeMinion) + lbc.ingressLister.Add(&teaMinion) cafeMasterIngEx, err := lbc.createIngress(&cafeMaster) if err != nil { @@ -564,12 +564,12 @@ func getMergableDefaults() (cafeMaster, coffeeMinion, teaMinion extensions.Ingre lbc = LoadBalancerController{ client: fakeClient, ingressClass: "nginx", - cnf: cnf, + configurator: cnf, } lbc.svcLister, _ = cache.NewInformer( cache.NewListWatchFromClient(lbc.client.ExtensionsV1beta1().RESTClient(), "services", "default", fields.Everything()), &extensions.Ingress{}, time.Duration(1), nil) - lbc.ingLister.Store, _ = cache.NewInformer( + lbc.ingressLister.Store, _ = cache.NewInformer( cache.NewListWatchFromClient(lbc.client.ExtensionsV1beta1().RESTClient(), "ingresses", "default", fields.Everything()), &extensions.Ingress{}, time.Duration(1), nil) coffeeService := v1.Service{ @@ -786,7 +786,7 @@ func TestGetServicePortForIngressPort(t *testing.T) { lbc := LoadBalancerController{ client: fakeClient, ingressClass: "nginx", - cnf: cnf, + configurator: cnf, } svc := v1.Service{ TypeMeta: meta_v1.TypeMeta{}, @@ -940,15 +940,15 @@ func TestFindIngressesForSecret(t *testing.T) { lbc := LoadBalancerController{ client: fakeClient, ingressClass: "nginx", - cnf: cnf, - nginxPlus: true, + configurator: cnf, + isNginxPlus: true, } - lbc.ingLister.Store, _ = cache.NewInformer( + lbc.ingressLister.Store, _ = cache.NewInformer( cache.NewListWatchFromClient(lbc.client.ExtensionsV1beta1().RESTClient(), "ingresses", "default", fields.Everything()), &extensions.Ingress{}, time.Duration(1), nil) - lbc.secrLister.Store, lbc.secrController = cache.NewInformer( + lbc.secretLister.Store, lbc.secretController = cache.NewInformer( cache.NewListWatchFromClient(lbc.client.Core().RESTClient(), "secrets", "default", fields.Everything()), &v1.Secret{}, time.Duration(1), nil) @@ -964,8 +964,8 @@ func TestFindIngressesForSecret(t *testing.T) { t.Fatalf("Ingress was not added: %v", err) } - lbc.ingLister.Add(&test.ingress) - lbc.secrLister.Add(&test.secret) + lbc.ingressLister.Add(&test.ingress) + lbc.secretLister.Add(&test.secret) nonMinions, minions, err := lbc.findIngressesForSecret(test.secret.ObjectMeta.Namespace, test.secret.ObjectMeta.Name) if err != nil { diff --git a/internal/controller/utils.go b/internal/controller/utils.go index 90ad817190..33f11ed359 100644 --- a/internal/controller/utils.go +++ b/internal/controller/utils.go @@ -31,9 +31,9 @@ import ( "github.com/golang/glog" ) -// taskQueue manages a work queue through an independent worker that +// TaskQueue manages a work queue through an independent worker that // invokes the given sync function for every work item inserted. -type taskQueue struct { +type TaskQueue struct { // queue is the work queue the worker polls queue *workqueue.Type // sync is called for each item in the queue @@ -42,12 +42,12 @@ type taskQueue struct { workerDone chan struct{} } -func (t *taskQueue) run(period time.Duration, stopCh <-chan struct{}) { +func (t *TaskQueue) run(period time.Duration, stopCh <-chan struct{}) { wait.Until(t.worker, period, stopCh) } // enqueue enqueues ns/name of the given api object in the task queue. -func (t *taskQueue) enqueue(obj interface{}) { +func (t *TaskQueue) enqueue(obj interface{}) { key, err := keyFunc(obj) if err != nil { glog.V(3).Infof("Couldn't get key for object %v: %v", obj, err) @@ -65,12 +65,12 @@ func (t *taskQueue) enqueue(obj interface{}) { t.queue.Add(task) } -func (t *taskQueue) requeue(task Task, err error) { +func (t *TaskQueue) requeue(task Task, err error) { glog.Errorf("Requeuing %v, err %v", task.Key, err) t.queue.Add(task) } -func (t *taskQueue) requeueAfter(task Task, err error, after time.Duration) { +func (t *TaskQueue) requeueAfter(task Task, err error, after time.Duration) { glog.Errorf("Requeuing %v after %s, err %v", task.Key, after.String(), err) go func(task Task, after time.Duration) { time.Sleep(after) @@ -79,7 +79,7 @@ func (t *taskQueue) requeueAfter(task Task, err error, after time.Duration) { } // worker processes work in the queue through sync. -func (t *taskQueue) worker() { +func (t *TaskQueue) worker() { for { task, quit := t.queue.Get() if quit { @@ -93,15 +93,15 @@ func (t *taskQueue) worker() { } // shutdown shuts down the work queue and waits for the worker to ACK -func (t *taskQueue) shutdown() { +func (t *TaskQueue) shutdown() { t.queue.ShutDown() <-t.workerDone } // NewTaskQueue creates a new task queue with the given sync function. // The sync function is called for every element inserted into the queue. -func NewTaskQueue(syncFn func(Task)) *taskQueue { - return &taskQueue{ +func NewTaskQueue(syncFn func(Task)) *TaskQueue { + return &TaskQueue{ queue: workqueue.New(), sync: syncFn, workerDone: make(chan struct{}), @@ -126,7 +126,7 @@ const ( Service ) -// Task is an element of a taskQueue +// Task is an element of a TaskQueue type Task struct { Kind Kind Key string From 961e59103d9beb173006515655ed84a5c8777ab4 Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Sun, 26 Aug 2018 10:55:15 +0100 Subject: [PATCH 05/10] Extract handlers, reduce complexity of creating new Controller. --- cmd/nginx-ingress/main.go | 36 +- internal/controller/controller.go | 538 +++++++----------------- internal/controller/status.go | 3 +- internal/handlers/configMap.go | 50 +++ internal/handlers/endpoint.go | 43 ++ internal/handlers/ingress.go | 64 +++ internal/handlers/leader.go | 20 + internal/handlers/secret.go | 59 +++ internal/handlers/service.go | 59 +++ internal/queue/queue.go | 89 ++++ internal/queue/task.go | 59 +++ internal/{controller => utils}/utils.go | 166 ++------ 12 files changed, 665 insertions(+), 521 deletions(-) create mode 100644 internal/handlers/configMap.go create mode 100644 internal/handlers/endpoint.go create mode 100644 internal/handlers/ingress.go create mode 100644 internal/handlers/leader.go create mode 100644 internal/handlers/secret.go create mode 100644 internal/handlers/service.go create mode 100644 internal/queue/queue.go create mode 100644 internal/queue/task.go rename internal/{controller => utils}/utils.go (58%) diff --git a/cmd/nginx-ingress/main.go b/cmd/nginx-ingress/main.go index a5c3b33cf4..b8545c0f29 100644 --- a/cmd/nginx-ingress/main.go +++ b/cmd/nginx-ingress/main.go @@ -14,8 +14,10 @@ import ( "github.com/golang/glog" "github.com/nginxinc/kubernetes-ingress/internal/controller" + "github.com/nginxinc/kubernetes-ingress/internal/handlers" "github.com/nginxinc/kubernetes-ingress/internal/nginx" "github.com/nginxinc/kubernetes-ingress/internal/nginx/plus" + "github.com/nginxinc/kubernetes-ingress/internal/utils" api_v1 "k8s.io/api/core/v1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -151,7 +153,7 @@ func main() { ngxc := nginx.NewNginxController("/etc/nginx/", local) if *defaultServerSecret != "" { - ns, name, err := controller.ParseNamespaceName(*defaultServerSecret) + ns, name, err := utils.ParseNamespaceName(*defaultServerSecret) if err != nil { glog.Fatalf("Error parsing the default-server-tls-secret argument: %v", err) } @@ -175,7 +177,7 @@ func main() { cfg := nginx.NewDefaultConfig() if *nginxConfigMaps != "" { - ns, name, err := controller.ParseNamespaceName(*nginxConfigMaps) + ns, name, err := utils.ParseNamespaceName(*nginxConfigMaps) if err != nil { glog.Fatalf("Error parsing the nginx-configmaps argument: %v", err) } @@ -234,7 +236,6 @@ func main() { ResyncPeriod: 30 * time.Second, Namespace: *watchNamespace, NginxConfigurator: cnf, - NginxConfigMaps: *nginxConfigMaps, DefaultServerSecret: *defaultServerSecret, IsNginxPlus: *nginxPlus, IngressClass: *ingressClass, @@ -244,7 +245,36 @@ func main() { ReportIngressStatus: *reportIngressStatus, IsLeaderElectionEnabled: *leaderElectionEnabled, } + lbc := controller.NewLoadBalancerController(lbcInput) + + // create handlers for resources we care about + ingressHandlers := handlers.CreateIngressHandlers(lbc) + secretHandlers := handlers.CreateSecretHandlers(lbc) + serviceHandlers := handlers.CreateServiceHandlers(lbc) + endpointHandlers := handlers.CreateEndpointHandlers(lbc) + + lbc.AddSecretHandler(secretHandlers) + lbc.AddIngressHandler(ingressHandlers) + lbc.AddServiceHandler(serviceHandlers) + lbc.AddEndpointHandler(endpointHandlers) + + if *nginxConfigMaps != "" { + nginxConfigMapsNS, nginxConfigMapsName, err := utils.ParseNamespaceName(*nginxConfigMaps) + if err != nil { + glog.Warning(err) + } else { + lbc.WatchNginxConfigMaps() + configMapHandlers := handlers.CreateConfigMapHandlers(lbc, nginxConfigMapsName) + lbc.AddConfigMapHandler(configMapHandlers, nginxConfigMapsNS) + } + } + + if lbcInput.ReportIngressStatus && lbcInput.IsLeaderElectionEnabled { + leaderHandler := handlers.CreateLeaderHandler(lbc) + lbc.AddLeaderHandler(leaderHandler) + } + go handleTermination(lbc, ngxc, nginxDone) lbc.Run() diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 09a9a0c7a9..0f77f40c08 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -18,13 +18,14 @@ package controller import ( "fmt" - "reflect" - "strings" "time" "github.com/golang/glog" "github.com/nginxinc/kubernetes-ingress/internal/nginx" + "github.com/nginxinc/kubernetes-ingress/internal/queue" + "github.com/nginxinc/kubernetes-ingress/internal/utils" + "k8s.io/api/extensions/v1beta1" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" @@ -55,12 +56,12 @@ type LoadBalancerController struct { endpointController cache.Controller configMapController cache.Controller secretController cache.Controller - ingressLister StoreToIngressLister + ingressLister utils.StoreToIngressLister svcLister cache.Store - endpointLister StoreToEndpointLister - configMapLister StoreToConfigMapLister - secretLister StoreToSecretLister - syncQueue *TaskQueue + endpointLister utils.StoreToEndpointLister + configMapLister utils.StoreToConfigMapLister + secretLister utils.StoreToSecretLister + syncQueue *queue.TaskQueue stop chan struct{} configurator *nginx.Configurator watchNginxConfigMaps bool @@ -73,6 +74,9 @@ type LoadBalancerController struct { leaderElector *leaderelection.LeaderElector reportIngressStatus bool isLeaderElectionEnabled bool + resync time.Duration + namespace string + controllerNamespace string } var keyFunc = cache.DeletionHandlingMetaNamespaceKeyFunc @@ -83,7 +87,6 @@ type NewLoadBalancerControllerInput struct { ResyncPeriod time.Duration Namespace string NginxConfigurator *nginx.Configurator - NginxConfigMaps string DefaultServerSecret string IsNginxPlus bool IngressClass string @@ -106,6 +109,9 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc useIngressClassOnly: input.UseIngressClassOnly, reportIngressStatus: input.ReportIngressStatus, isLeaderElectionEnabled: input.IsLeaderElectionEnabled, + resync: input.ResyncPeriod, + namespace: input.Namespace, + controllerNamespace: input.ControllerNamespace, } eventBroadcaster := record.NewBroadcaster() @@ -116,324 +122,112 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc lbc.recorder = eventBroadcaster.NewRecorder(scheme.Scheme, api_v1.EventSource{Component: "nginx-ingress-controller"}) - lbc.syncQueue = NewTaskQueue(lbc.sync) + lbc.syncQueue = queue.NewTaskQueue(lbc.sync) glog.V(3).Infof("Nginx Ingress Controller has class: %v", input.IngressClass) - ingressHandlers := cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - ingress := obj.(*extensions.Ingress) - if !lbc.isNginxIngress(ingress) { - glog.Infof("Ignoring Ingress %v based on Annotation %v", ingress.Name, ingressClassKey) - return - } - glog.V(3).Infof("Adding Ingress: %v", ingress.Name) - lbc.syncQueue.enqueue(obj) - }, - DeleteFunc: func(obj interface{}) { - ingress, isIng := obj.(*extensions.Ingress) - if !isIng { - deletedState, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.V(3).Infof("Error received unexpected object: %v", obj) - return - } - ingress, ok = deletedState.Obj.(*extensions.Ingress) - if !ok { - glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Ingress object: %v", deletedState.Obj) - return - } - } - if !lbc.isNginxIngress(ingress) { - return - } - if isMinion(ingress) { - master, err := lbc.findMasterForMinion(ingress) - if err != nil { - glog.Infof("Ignoring Ingress %v(Minion): %v", ingress.Name, err) - return - } - glog.V(3).Infof("Removing Ingress: %v(Minion) for %v(Master)", ingress.Name, master.Name) - lbc.syncQueue.enqueue(master) - } else { - glog.V(3).Infof("Removing Ingress: %v", ingress.Name) - lbc.syncQueue.enqueue(obj) - } - }, - UpdateFunc: func(old, current interface{}) { - c := current.(*extensions.Ingress) - o := old.(*extensions.Ingress) - if !lbc.isNginxIngress(c) { - return - } - if hasChanges(o, c) { - glog.V(3).Infof("Ingress %v changed, syncing", c.Name) - lbc.syncQueue.enqueue(c) - } - }, + lbc.statusUpdater = &StatusUpdater{ + client: input.KubeClient, + namespace: input.ControllerNamespace, + externalServiceName: input.ExternalServiceName, + ingLister: &lbc.ingressLister, + keyFunc: keyFunc, } - lbc.ingressLister.Store, lbc.ingressController = cache.NewInformer( + return &lbc +} + +func (lbc *LoadBalancerController) UpdateManagedAndMergeableIngresses(ingresses []v1beta1.Ingress, mergeableIngresses map[string]*nginx.MergeableIngresses) error { + return lbc.statusUpdater.UpdateManagedAndMergeableIngresses(ingresses, mergeableIngresses) +} + +func (lbc *LoadBalancerController) AddLeaderHandler(leaderHandler leaderelection.LeaderCallbacks) { + var err error + lbc.leaderElector, err = NewLeaderElector(lbc.client, leaderHandler, lbc.controllerNamespace) + if err != nil { + glog.V(3).Infof("Error starting LeaderElection: %v", err) + } +} + +func (lbc *LoadBalancerController) GetIngressClassKey() string { + return ingressClassKey +} + +func (lbc *LoadBalancerController) AddSyncQueue(item interface{}) { + lbc.syncQueue.Enqueue(item) +} + +func (lbc *LoadBalancerController) WatchNginxConfigMaps() { + lbc.watchNginxConfigMaps = true +} + +func (lbc *LoadBalancerController) AddSecretHandler(handlers cache.ResourceEventHandlerFuncs) { + lbc.secretLister.Store, lbc.secretController = cache.NewInformer( cache.NewListWatchFromClient( - lbc.client.Extensions().RESTClient(), - "ingresses", - input.Namespace, + lbc.client.Core().RESTClient(), + "secrets", + lbc.namespace, fields.Everything()), - &extensions.Ingress{}, - input.ResyncPeriod, - ingressHandlers, + &api_v1.Secret{}, + lbc.resync, + handlers, ) +} - svcHandlers := cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - svc := obj.(*api_v1.Service) - if lbc.isExternalServiceForStatus(svc) { - lbc.syncQueue.enqueue(svc) - return - } - glog.V(3).Infof("Adding service: %v", svc.Name) - lbc.enqueueIngressForService(svc) - }, - DeleteFunc: func(obj interface{}) { - svc, isSvc := obj.(*api_v1.Service) - if !isSvc { - deletedState, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.V(3).Infof("Error received unexpected object: %v", obj) - return - } - svc, ok = deletedState.Obj.(*api_v1.Service) - if !ok { - glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Service object: %v", deletedState.Obj) - return - } - } - if lbc.isExternalServiceForStatus(svc) { - lbc.syncQueue.enqueue(svc) - return - } - - glog.V(3).Infof("Removing service: %v", svc.Name) - lbc.enqueueIngressForService(svc) - - }, - UpdateFunc: func(old, cur interface{}) { - if !reflect.DeepEqual(old, cur) { - svc := cur.(*api_v1.Service) - if lbc.isExternalServiceForStatus(svc) { - lbc.syncQueue.enqueue(svc) - return - } - glog.V(3).Infof("Service %v changed, syncing", svc.Name) - lbc.enqueueIngressForService(svc) - } - }, - } +func (lbc *LoadBalancerController) AddServiceHandler(handlers cache.ResourceEventHandlerFuncs) { lbc.svcLister, lbc.svcController = cache.NewInformer( cache.NewListWatchFromClient( lbc.client.Core().RESTClient(), "services", - input.Namespace, + lbc.namespace, fields.Everything()), &api_v1.Service{}, - input.ResyncPeriod, - svcHandlers, + lbc.resync, + handlers, ) +} - endpointHandlers := cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - endpoint := obj.(*api_v1.Endpoints) - glog.V(3).Infof("Adding endpoints: %v", endpoint.Name) - lbc.syncQueue.enqueue(obj) - }, - DeleteFunc: func(obj interface{}) { - endpoint, isEndpoint := obj.(*api_v1.Endpoints) - if !isEndpoint { - deletedState, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.V(3).Infof("Error received unexpected object: %v", obj) - return - } - endpoint, ok = deletedState.Obj.(*api_v1.Endpoints) - if !ok { - glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Endpoints object: %v", deletedState.Obj) - return - } - } - glog.V(3).Infof("Removing endpoints: %v", endpoint.Name) - lbc.syncQueue.enqueue(obj) - }, - UpdateFunc: func(old, cur interface{}) { - if !reflect.DeepEqual(old, cur) { - glog.V(3).Infof("Endpoints %v changed, syncing", cur.(*api_v1.Endpoints).Name) - lbc.syncQueue.enqueue(cur) - } - }, - } +func (lbc *LoadBalancerController) AddIngressHandler(handlers cache.ResourceEventHandlerFuncs) { + lbc.ingressLister.Store, lbc.ingressController = cache.NewInformer( + cache.NewListWatchFromClient( + lbc.client.Extensions().RESTClient(), + "ingresses", + lbc.namespace, + fields.Everything()), + &extensions.Ingress{}, + lbc.resync, + handlers, + ) +} +func (lbc *LoadBalancerController) AddEndpointHandler(handlers cache.ResourceEventHandlerFuncs) { lbc.endpointLister.Store, lbc.endpointController = cache.NewInformer( cache.NewListWatchFromClient( lbc.client.Core().RESTClient(), "endpoints", - input.Namespace, + lbc.namespace, fields.Everything()), &api_v1.Endpoints{}, - input.ResyncPeriod, - endpointHandlers, + lbc.resync, + handlers, ) +} - secretHandlers := cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - secret := obj.(*api_v1.Secret) - if err := lbc.ValidateSecret(secret); err != nil { - return - } - nsname := secret.Namespace + "/" + secret.Name - if nsname == lbc.defaultServerSecret { - glog.V(3).Infof("Adding default server Secret: %v", secret.Name) - lbc.syncQueue.enqueue(obj) - } - }, - DeleteFunc: func(obj interface{}) { - secret, isSecr := obj.(*api_v1.Secret) - if !isSecr { - deletedState, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.V(3).Infof("Error received unexpected object: %v", obj) - return - } - secret, ok = deletedState.Obj.(*api_v1.Secret) - if !ok { - glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Secret object: %v", deletedState.Obj) - return - } - } - if err := lbc.ValidateSecret(secret); err != nil { - return - } - - glog.V(3).Infof("Removing Secret: %v", secret.Name) - lbc.syncQueue.enqueue(obj) - }, - UpdateFunc: func(old, cur interface{}) { - errOld := lbc.ValidateSecret(old.(*api_v1.Secret)) - errCur := lbc.ValidateSecret(cur.(*api_v1.Secret)) - if errOld != nil && errCur != nil { - return - } - - if !reflect.DeepEqual(old, cur) { - glog.V(3).Infof("Secret %v changed, syncing", cur.(*api_v1.Secret).Name) - lbc.syncQueue.enqueue(cur) - } - }, - } - - lbc.secretLister.Store, lbc.secretController = cache.NewInformer( +func (lbc *LoadBalancerController) AddConfigMapHandler(handlers cache.ResourceEventHandlerFuncs, namespace string) { + lbc.configMapLister.Store, lbc.configMapController = cache.NewInformer( cache.NewListWatchFromClient( lbc.client.Core().RESTClient(), - "secrets", - input.Namespace, + "configmaps", + namespace, fields.Everything()), - &api_v1.Secret{}, - input.ResyncPeriod, - secretHandlers, + &api_v1.ConfigMap{}, + lbc.resync, + handlers, ) - - if input.NginxConfigMaps != "" { - nginxConfigMapsNS, nginxConfigMapsName, err := ParseNamespaceName(input.NginxConfigMaps) - if err != nil { - glog.Warning(err) - } else { - lbc.watchNginxConfigMaps = true - - configMapHandlers := cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - configMap := obj.(*api_v1.ConfigMap) - if configMap.Name == nginxConfigMapsName { - glog.V(3).Infof("Adding ConfigMap: %v", configMap.Name) - lbc.syncQueue.enqueue(obj) - } - }, - DeleteFunc: func(obj interface{}) { - configMap, isConfigMap := obj.(*api_v1.ConfigMap) - if !isConfigMap { - deletedState, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.V(3).Infof("Error received unexpected object: %v", obj) - return - } - configMap, ok = deletedState.Obj.(*api_v1.ConfigMap) - if !ok { - glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-ConfigMap object: %v", deletedState.Obj) - return - } - } - if configMap.Name == nginxConfigMapsName { - glog.V(3).Infof("Removing ConfigMap: %v", configMap.Name) - lbc.syncQueue.enqueue(obj) - } - }, - UpdateFunc: func(old, cur interface{}) { - if !reflect.DeepEqual(old, cur) { - configMap := cur.(*api_v1.ConfigMap) - if configMap.Name == nginxConfigMapsName { - glog.V(3).Infof("ConfigMap %v changed, syncing", cur.(*api_v1.ConfigMap).Name) - lbc.syncQueue.enqueue(cur) - } - } - }, - } - - lbc.configMapLister.Store, lbc.configMapController = cache.NewInformer( - cache.NewListWatchFromClient( - lbc.client.Core().RESTClient(), - "configmaps", - nginxConfigMapsNS, - fields.Everything()), - &api_v1.ConfigMap{}, - input.ResyncPeriod, - configMapHandlers, - ) - } - } - - // statusUpdater requires ingLister to be instantiated, above. - lbc.statusUpdater = &StatusUpdater{ - client: input.KubeClient, - namespace: input.ControllerNamespace, - externalServiceName: input.ExternalServiceName, - ingLister: &lbc.ingressLister, - keyFunc: keyFunc, - } - - if input.ReportIngressStatus && input.IsLeaderElectionEnabled { - leaderCallbacks := leaderelection.LeaderCallbacks{ - OnStartedLeading: func(stop <-chan struct{}) { - glog.V(3).Info("started leading, updating ingress status") - ingresses, mergeableIngresses := lbc.getManagedIngresses() - err := lbc.statusUpdater.UpdateManagedAndMergeableIngresses(ingresses, mergeableIngresses) - if err != nil { - glog.V(3).Infof("error updating status when starting leading: %v", err) - } - }, - } - - var err error - lbc.leaderElector, err = NewLeaderElector(input.KubeClient, leaderCallbacks, input.ControllerNamespace) - if err != nil { - glog.V(3).Infof("Error starting LeaderElection: %v", err) - } - } - - return &lbc } -// hasChanges ignores Status or ResourceVersion changes -func hasChanges(old *extensions.Ingress, current *extensions.Ingress) bool { - old.Status.LoadBalancer.Ingress = current.Status.LoadBalancer.Ingress - old.ResourceVersion = current.ResourceVersion - return !reflect.DeepEqual(old, current) +func (lbc *LoadBalancerController) GetDefaultServerSecret() string { + return lbc.defaultServerSecret } // Run starts the loadbalancer controller @@ -448,7 +242,7 @@ func (lbc *LoadBalancerController) Run() { go lbc.configMapController.Run(lbc.stop) } go lbc.ingressController.Run(lbc.stop) - go lbc.syncQueue.run(time.Second, lbc.stop) + go lbc.syncQueue.Run(time.Second, lbc.stop) <-lbc.stop } @@ -456,16 +250,16 @@ func (lbc *LoadBalancerController) Run() { func (lbc *LoadBalancerController) Stop() { close(lbc.stop) - lbc.syncQueue.shutdown() + lbc.syncQueue.Shutdown() } -func (lbc *LoadBalancerController) syncEndpoint(task Task) { +func (lbc *LoadBalancerController) syncEndpoint(task queue.Task) { key := task.Key glog.V(3).Infof("Syncing endpoints %v", key) obj, endpExists, err := lbc.endpointLister.GetByKey(key) if err != nil { - lbc.syncQueue.requeue(task, err) + lbc.syncQueue.Requeue(task, err) return } @@ -473,11 +267,11 @@ func (lbc *LoadBalancerController) syncEndpoint(task Task) { ings := lbc.getIngressForEndpoints(obj) for _, ing := range ings { - if !lbc.isNginxIngress(&ing) { + if !lbc.IsNginxIngress(&ing) { continue } - if isMinion(&ing) { - master, err := lbc.findMasterForMinion(&ing) + if utils.IsMinion(&ing) { + master, err := lbc.FindMasterForMinion(&ing) if err != nil { glog.Errorf("Ignoring Ingress %v(Minion): %v", ing.Name, err) continue @@ -515,13 +309,13 @@ func (lbc *LoadBalancerController) syncEndpoint(task Task) { } } -func (lbc *LoadBalancerController) syncConfig(task Task) { +func (lbc *LoadBalancerController) syncConfig(task queue.Task) { key := task.Key glog.V(3).Infof("Syncing configmap %v", key) obj, configExists, err := lbc.configMapLister.GetByKey(key) if err != nil { - lbc.syncQueue.requeue(task, err) + lbc.syncQueue.Requeue(task, err) return } cfg := nginx.NewDefaultConfig() @@ -533,7 +327,7 @@ func (lbc *LoadBalancerController) syncConfig(task Task) { lbc.statusUpdater.SaveStatusFromExternalStatus(cfgm.Data["external-status-address"]) } - ingresses, mergeableIngresses := lbc.getManagedIngresses() + ingresses, mergeableIngresses := lbc.GetManagedIngresses() ingExes := lbc.ingressesToIngressExes(ingresses) if lbc.reportStatusEnabled() { @@ -572,18 +366,18 @@ func (lbc *LoadBalancerController) syncConfig(task Task) { } } -// getManagedIngresses gets Ingress resources that the IC is currently responsible for -func (lbc *LoadBalancerController) getManagedIngresses() ([]extensions.Ingress, map[string]*nginx.MergeableIngresses) { +// GetManagedIngresses gets Ingress resources that the IC is currently responsible for +func (lbc *LoadBalancerController) GetManagedIngresses() ([]extensions.Ingress, map[string]*nginx.MergeableIngresses) { mergeableIngresses := make(map[string]*nginx.MergeableIngresses) var managedIngresses []extensions.Ingress ings, _ := lbc.ingressLister.List() for i := range ings.Items { ing := ings.Items[i] - if !lbc.isNginxIngress(&ing) { + if !lbc.IsNginxIngress(&ing) { continue } - if isMinion(&ing) { - master, err := lbc.findMasterForMinion(&ing) + if utils.IsMinion(&ing) { + master, err := lbc.FindMasterForMinion(&ing) if err != nil { glog.Errorf("Ignoring Ingress %v(Minion): %v", ing, err) continue @@ -621,33 +415,33 @@ func (lbc *LoadBalancerController) ingressesToIngressExes(ings []extensions.Ingr return ingExes } -func (lbc *LoadBalancerController) sync(task Task) { +func (lbc *LoadBalancerController) sync(task queue.Task) { glog.V(3).Infof("Syncing %v", task.Key) switch task.Kind { - case Ingress: + case queue.Ingress: lbc.syncIng(task) - case IngressMinion: + case queue.IngressMinion: lbc.syncIngMinion(task) - case ConfigMap: + case queue.ConfigMap: lbc.syncConfig(task) return - case Endpoints: + case queue.Endpoints: lbc.syncEndpoint(task) return - case Secret: + case queue.Secret: lbc.syncSecret(task) return - case Service: + case queue.Service: lbc.syncExternalService(task) } } -func (lbc *LoadBalancerController) syncIngMinion(task Task) { +func (lbc *LoadBalancerController) syncIngMinion(task queue.Task) { key := task.Key obj, ingExists, err := lbc.ingressLister.Store.GetByKey(key) if err != nil { - lbc.syncQueue.requeue(task, err) + lbc.syncQueue.Requeue(task, err) return } @@ -659,28 +453,28 @@ func (lbc *LoadBalancerController) syncIngMinion(task Task) { minion := obj.(*extensions.Ingress) - master, err := lbc.findMasterForMinion(minion) + master, err := lbc.FindMasterForMinion(minion) if err != nil { - lbc.syncQueue.requeueAfter(task, err, 5*time.Second) + lbc.syncQueue.RequeueAfter(task, err, 5*time.Second) return } _, err = lbc.createIngress(minion) if err != nil { - lbc.syncQueue.requeueAfter(task, err, 5*time.Second) + lbc.syncQueue.RequeueAfter(task, err, 5*time.Second) if !lbc.configurator.HasMinion(master, minion) { return } } - lbc.syncQueue.enqueue(master) + lbc.syncQueue.Enqueue(master) } -func (lbc *LoadBalancerController) syncIng(task Task) { +func (lbc *LoadBalancerController) syncIng(task queue.Task) { key := task.Key ing, ingExists, err := lbc.ingressLister.GetByKeySafe(key) if err != nil { - lbc.syncQueue.requeue(task, err) + lbc.syncQueue.Requeue(task, err) return } @@ -694,10 +488,10 @@ func (lbc *LoadBalancerController) syncIng(task Task) { } else { glog.V(2).Infof("Adding or Updating Ingress: %v\n", key) - if isMaster(ing) { + if utils.IsMaster(ing) { mergeableIngExs, err := lbc.createMergableIngresses(ing) if err != nil { - lbc.syncQueue.requeueAfter(task, err, 5*time.Second) + lbc.syncQueue.RequeueAfter(task, err, 5*time.Second) lbc.recorder.Eventf(ing, api_v1.EventTypeWarning, "Rejected", "%v was rejected: %v", key, err) if lbc.reportStatusEnabled() { err = lbc.statusUpdater.ClearIngressStatus(*ing) @@ -734,7 +528,7 @@ func (lbc *LoadBalancerController) syncIng(task Task) { } ingEx, err := lbc.createIngress(ing) if err != nil { - lbc.syncQueue.requeueAfter(task, err, 5*time.Second) + lbc.syncQueue.RequeueAfter(task, err, 5*time.Second) lbc.recorder.Eventf(ing, api_v1.EventTypeWarning, "Rejected", "%v was rejected: %v", key, err) if lbc.reportStatusEnabled() { err = lbc.statusUpdater.ClearIngressStatus(*ing) @@ -762,14 +556,14 @@ func (lbc *LoadBalancerController) syncIng(task Task) { // syncExternalService does not sync all services. // We only watch the Service specified by the external-service flag. -func (lbc *LoadBalancerController) syncExternalService(task Task) { +func (lbc *LoadBalancerController) syncExternalService(task queue.Task) { key := task.Key obj, exists, err := lbc.svcLister.GetByKey(key) if err != nil { - lbc.syncQueue.requeue(task, err) + lbc.syncQueue.Requeue(task, err) return } - statusIngs, mergableIngs := lbc.getManagedIngresses() + statusIngs, mergableIngs := lbc.GetManagedIngresses() if !exists { // service got removed lbc.statusUpdater.ClearStatusFromExternalService() @@ -786,7 +580,7 @@ func (lbc *LoadBalancerController) syncExternalService(task Task) { } // isExternalServiceForStatus matches the service specified by the external-service arg -func (lbc *LoadBalancerController) isExternalServiceForStatus(svc *api_v1.Service) bool { +func (lbc *LoadBalancerController) IsExternalServiceForStatus(svc *api_v1.Service) bool { return lbc.statusUpdater.namespace == svc.Namespace && lbc.statusUpdater.externalServiceName == svc.Name } @@ -801,15 +595,15 @@ func (lbc *LoadBalancerController) reportStatusEnabled() bool { return false } -func (lbc *LoadBalancerController) syncSecret(task Task) { +func (lbc *LoadBalancerController) syncSecret(task queue.Task) { key := task.Key obj, secrExists, err := lbc.secretLister.Store.GetByKey(key) if err != nil { - lbc.syncQueue.requeue(task, err) + lbc.syncQueue.Requeue(task, err) return } - namespace, name, err := ParseNamespaceName(key) + namespace, name, err := utils.ParseNamespaceName(key) if err != nil { glog.Warningf("Secret key %v is invalid: %v", key, err) return @@ -818,7 +612,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { nonMinions, minions, err := lbc.findIngressesForSecret(namespace, name) if err != nil { glog.Warningf("Failed to find Ingress resources for Secret %v: %v", key, err) - lbc.syncQueue.requeueAfter(task, err, 5*time.Second) + lbc.syncQueue.RequeueAfter(task, err, 5*time.Second) } glog.V(2).Infof("Found %v Non-Minion and %v Minion Ingress resources with Secret %v", len(nonMinions), len(minions), key) @@ -827,7 +621,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { glog.V(2).Infof("Deleting Secret: %v\n", key) for _, minion := range minions { - master, err := lbc.findMasterForMinion(&minion) + master, err := lbc.FindMasterForMinion(&minion) if err != nil { glog.Errorf("Ignoring Ingress %v(Minion): %v", minion.Name, err) continue @@ -843,7 +637,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { } lbc.recorder.Eventf(&minion, api_v1.EventTypeWarning, "Rejected", "%v/%v was rejected due to deleted Secret %v: %v", minion.Namespace, minion.Name, key) lbc.recorder.Eventf(master, api_v1.EventTypeWarning, "Rejected", "Minion %v/%v was rejected due to deleted Secret %v: %v", minion.Namespace, minion.Name, key) - lbc.syncQueue.enqueue(&minion) + lbc.syncQueue.Enqueue(&minion) } if err := lbc.configurator.DeleteSecret(key, nonMinions); err != nil { @@ -851,7 +645,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { } for _, ing := range nonMinions { - lbc.syncQueue.enqueue(&ing) + lbc.syncQueue.Enqueue(&ing) lbc.recorder.Eventf(&ing, api_v1.EventTypeWarning, "Rejected", "%v/%v was rejected due to deleted Secret %v", ing.Namespace, ing.Name, key) } @@ -887,7 +681,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { glog.Errorf("Couldn't validate secret %v: %v", key, err) for _, minion := range minions { - master, err := lbc.findMasterForMinion(&minion) + master, err := lbc.FindMasterForMinion(&minion) if err != nil { glog.Errorf("Ignoring Ingress %v(Minion): %v", minion.Name, err) continue @@ -903,14 +697,14 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { } lbc.recorder.Eventf(&minion, api_v1.EventTypeWarning, "Rejected", "%v/%v was rejected due to invalid Secret %v: %v", minion.Namespace, minion.Name, key, err) lbc.recorder.Eventf(master, api_v1.EventTypeWarning, "Rejected", "Minion %v/%v was rejected due to invalid Secret %v: %v", minion.Namespace, minion.Name, key, err) - lbc.syncQueue.enqueue(&minion) + lbc.syncQueue.Enqueue(&minion) } if err := lbc.configurator.DeleteSecret(key, nonMinions); err != nil { glog.Errorf("Error when deleting Secret: %v: %v", key, err) } for _, ing := range nonMinions { - lbc.syncQueue.enqueue(&ing) + lbc.syncQueue.Enqueue(&ing) lbc.recorder.Eventf(&ing, api_v1.EventTypeWarning, "Rejected", "%v/%v was rejected due to invalid Secret %v: %v", ing.Namespace, ing.Name, key, err) } lbc.recorder.Eventf(secret, api_v1.EventTypeWarning, "Rejected", "%v was rejected: %v", key, err) @@ -924,7 +718,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { lbc.recorder.Eventf(&ing, api_v1.EventTypeWarning, "UpdatedWithError", "Configuration for %v/%v was updated, but not applied: %v", ing.Namespace, ing.Name, err) } for _, minion := range minions { - master, err := lbc.findMasterForMinion(&minion) + master, err := lbc.FindMasterForMinion(&minion) if err != nil { glog.Errorf("Ignoring Ingress %v(Minion): %v", minion.Name, err) continue @@ -938,7 +732,7 @@ func (lbc *LoadBalancerController) syncSecret(task Task) { lbc.recorder.Eventf(&ing, api_v1.EventTypeNormal, "Updated", "Configuration for %v/%v was updated", ing.Namespace, ing.Name) } for _, minion := range minions { - master, err := lbc.findMasterForMinion(&minion) + master, err := lbc.FindMasterForMinion(&minion) if err != nil { glog.Errorf("Ignoring Ingress %v(Minion): %v", minion.Name, err) continue @@ -963,11 +757,11 @@ items: continue } - if !lbc.isNginxIngress(&ing) { + if !lbc.IsNginxIngress(&ing) { continue } - if !isMinion(&ing) { + if !utils.IsMinion(&ing) { if !lbc.configurator.HasIngress(&ing) { continue } @@ -990,7 +784,7 @@ items: // we're dealing with a minion // minions can only have JWT secrets if lbc.isNginxPlus { - master, err := lbc.findMasterForMinion(&ing) + master, err := lbc.FindMasterForMinion(&ing) if err != nil { glog.Infof("Ignoring Ingress %v(Minion): %v", ing.Name, err) continue @@ -1011,14 +805,14 @@ items: return nonMinions, minions, nil } -func (lbc *LoadBalancerController) enqueueIngressForService(svc *api_v1.Service) { +func (lbc *LoadBalancerController) EnqueueIngressForService(svc *api_v1.Service) { ings := lbc.getIngressesForService(svc) for _, ing := range ings { - if !lbc.isNginxIngress(&ing) { + if !lbc.IsNginxIngress(&ing) { continue } - if isMinion(&ing) { - master, err := lbc.findMasterForMinion(&ing) + if utils.IsMinion(&ing) { + master, err := lbc.FindMasterForMinion(&ing) if err != nil { glog.Errorf("Ignoring Ingress %v(Minion): %v", ing.Name, err) continue @@ -1028,7 +822,7 @@ func (lbc *LoadBalancerController) enqueueIngressForService(svc *api_v1.Service) if !lbc.configurator.HasIngress(&ing) { continue } - lbc.syncQueue.enqueue(&ing) + lbc.syncQueue.Enqueue(&ing) } } @@ -1292,7 +1086,7 @@ func (lbc *LoadBalancerController) getTargetPort(svcPort *api_v1.ServicePort, sv pod := &pods.Items[0] - portNum, err := FindPort(pod, svcPort) + portNum, err := utils.FindPort(pod, svcPort) if err != nil { return 0, fmt.Errorf("Error finding named port %v in pod %s: %v", svcPort, pod.Name, err) } @@ -1314,19 +1108,9 @@ func (lbc *LoadBalancerController) getServiceForIngressBackend(backend *extensio return nil, fmt.Errorf("service %s doesn't exists", svcKey) } -// ParseNamespaceName parses the string in the / format and returns the name and the namespace. -// It returns an error in case the string does not follow the / format. -func ParseNamespaceName(value string) (ns string, name string, err error) { - res := strings.Split(value, "/") - if len(res) != 2 { - return "", "", fmt.Errorf("%q must follow the format /", value) - } - return res[0], res[1], nil -} - -// Check if resource ingress class annotation (if exists) is matching with ingress controller class +// IsNginxIngress checks if resource ingress class annotation (if exists) is matching with ingress controller class // If annotation is absent and use-ingress-class-only enabled - ingress resource would ignore -func (lbc *LoadBalancerController) isNginxIngress(ing *extensions.Ingress) bool { +func (lbc *LoadBalancerController) IsNginxIngress(ing *extensions.Ingress) bool { if class, exists := ing.Annotations[ingressClassKey]; exists { if lbc.useIngressClassOnly { return class == lbc.ingressClass @@ -1381,10 +1165,10 @@ func (lbc *LoadBalancerController) getMinionsForMaster(master *nginx.IngressEx) var minionPaths = make(map[string]*extensions.Ingress) for i := range ings.Items { - if !lbc.isNginxIngress(&ings.Items[i]) { + if !lbc.IsNginxIngress(&ings.Items[i]) { continue } - if !isMinion(&ings.Items[i]) { + if !utils.IsMinion(&ings.Items[i]) { continue } if ings.Items[i].Spec.Rules[0].Host != master.Ingress.Spec.Rules[0].Host { @@ -1427,21 +1211,21 @@ func (lbc *LoadBalancerController) getMinionsForMaster(master *nginx.IngressEx) return minions, nil } -// findMasterForHost returns a master for a given minion -func (lbc *LoadBalancerController) findMasterForMinion(minion *extensions.Ingress) (*extensions.Ingress, error) { +// FindMasterForMinion returns a master for a given minion +func (lbc *LoadBalancerController) FindMasterForMinion(minion *extensions.Ingress) (*extensions.Ingress, error) { ings, err := lbc.ingressLister.List() if err != nil { return &extensions.Ingress{}, err } for i := range ings.Items { - if !lbc.isNginxIngress(&ings.Items[i]) { + if !lbc.IsNginxIngress(&ings.Items[i]) { continue } if !lbc.configurator.HasIngress(&ings.Items[i]) { continue } - if !isMaster(&ings.Items[i]) { + if !utils.IsMaster(&ings.Items[i]) { continue } if ings.Items[i].Spec.Rules[0].Host != minion.Spec.Rules[0].Host { @@ -1493,17 +1277,3 @@ func (lbc *LoadBalancerController) createMergableIngresses(master *extensions.In return &mergeableIngresses, nil } - -func isMinion(ing *extensions.Ingress) bool { - if ing.Annotations["nginx.org/mergeable-ingress-type"] == "minion" { - return true - } - return false -} - -func isMaster(ing *extensions.Ingress) bool { - if ing.Annotations["nginx.org/mergeable-ingress-type"] == "master" { - return true - } - return false -} diff --git a/internal/controller/status.go b/internal/controller/status.go index 70151bb4b4..81488da414 100644 --- a/internal/controller/status.go +++ b/internal/controller/status.go @@ -7,6 +7,7 @@ import ( "github.com/golang/glog" "github.com/nginxinc/kubernetes-ingress/internal/nginx" + "github.com/nginxinc/kubernetes-ingress/internal/utils" api_v1 "k8s.io/api/core/v1" "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -25,7 +26,7 @@ type StatusUpdater struct { externalServiceAddresses []string status []api_v1.LoadBalancerIngress keyFunc func(obj interface{}) (string, error) - ingLister *StoreToIngressLister + ingLister *utils.StoreToIngressLister } // UpdateManagedAndMergeableIngresses handles the full return format of LoadBalancerController.getManagedIngresses diff --git a/internal/handlers/configMap.go b/internal/handlers/configMap.go new file mode 100644 index 0000000000..93cbc077a8 --- /dev/null +++ b/internal/handlers/configMap.go @@ -0,0 +1,50 @@ +package handlers + +import ( + "reflect" + + "github.com/golang/glog" + "github.com/nginxinc/kubernetes-ingress/internal/controller" + api_v1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/cache" +) + +func CreateConfigMapHandlers(lbc *controller.LoadBalancerController, name string) cache.ResourceEventHandlerFuncs { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + configMap := obj.(*api_v1.ConfigMap) + if configMap.Name == name { + glog.V(3).Infof("Adding ConfigMap: %v", configMap.Name) + lbc.AddSyncQueue(obj) + } + }, + DeleteFunc: func(obj interface{}) { + configMap, isConfigMap := obj.(*api_v1.ConfigMap) + if !isConfigMap { + deletedState, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + glog.V(3).Infof("Error received unexpected object: %v", obj) + return + } + configMap, ok = deletedState.Obj.(*api_v1.ConfigMap) + if !ok { + glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-ConfigMap object: %v", deletedState.Obj) + return + } + } + if configMap.Name == name { + glog.V(3).Infof("Removing ConfigMap: %v", configMap.Name) + lbc.AddSyncQueue(obj) + } + }, + UpdateFunc: func(old, cur interface{}) { + if !reflect.DeepEqual(old, cur) { + configMap := cur.(*api_v1.ConfigMap) + if configMap.Name == name { + glog.V(3).Infof("ConfigMap %v changed, syncing", cur.(*api_v1.ConfigMap).Name) + lbc.AddSyncQueue(cur) + } + } + }, + } +} diff --git a/internal/handlers/endpoint.go b/internal/handlers/endpoint.go new file mode 100644 index 0000000000..8186613204 --- /dev/null +++ b/internal/handlers/endpoint.go @@ -0,0 +1,43 @@ +package handlers + +import ( + "reflect" + + "github.com/golang/glog" + "github.com/nginxinc/kubernetes-ingress/internal/controller" + api_v1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/cache" +) + +func CreateEndpointHandlers(lbc *controller.LoadBalancerController) cache.ResourceEventHandlerFuncs { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + endpoint := obj.(*api_v1.Endpoints) + glog.V(3).Infof("Adding endpoints: %v", endpoint.Name) + lbc.AddSyncQueue(obj) + }, + DeleteFunc: func(obj interface{}) { + endpoint, isEndpoint := obj.(*api_v1.Endpoints) + if !isEndpoint { + deletedState, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + glog.V(3).Infof("Error received unexpected object: %v", obj) + return + } + endpoint, ok = deletedState.Obj.(*api_v1.Endpoints) + if !ok { + glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Endpoints object: %v", deletedState.Obj) + return + } + } + glog.V(3).Infof("Removing endpoints: %v", endpoint.Name) + lbc.AddSyncQueue(obj) + }, + UpdateFunc: func(old, cur interface{}) { + if !reflect.DeepEqual(old, cur) { + glog.V(3).Infof("Endpoints %v changed, syncing", cur.(*api_v1.Endpoints).Name) + lbc.AddSyncQueue(cur) + } + }, + } +} diff --git a/internal/handlers/ingress.go b/internal/handlers/ingress.go new file mode 100644 index 0000000000..50fe681128 --- /dev/null +++ b/internal/handlers/ingress.go @@ -0,0 +1,64 @@ +package handlers + +import ( + "github.com/golang/glog" + "github.com/nginxinc/kubernetes-ingress/internal/controller" + "github.com/nginxinc/kubernetes-ingress/internal/utils" + extensions "k8s.io/api/extensions/v1beta1" + "k8s.io/client-go/tools/cache" +) + +func CreateIngressHandlers(lbc *controller.LoadBalancerController) cache.ResourceEventHandlerFuncs { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + ingress := obj.(*extensions.Ingress) + if !lbc.IsNginxIngress(ingress) { + glog.Infof("Ignoring Ingress %v based on Annotation %v", ingress.Name, lbc.GetIngressClassKey()) + return + } + glog.V(3).Infof("Adding Ingress: %v", ingress.Name) + lbc.AddSyncQueue(obj) + }, + DeleteFunc: func(obj interface{}) { + ingress, isIng := obj.(*extensions.Ingress) + if !isIng { + deletedState, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + glog.V(3).Infof("Error received unexpected object: %v", obj) + return + } + ingress, ok = deletedState.Obj.(*extensions.Ingress) + if !ok { + glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Ingress object: %v", deletedState.Obj) + return + } + } + if !lbc.IsNginxIngress(ingress) { + return + } + if utils.IsMinion(ingress) { + master, err := lbc.FindMasterForMinion(ingress) + if err != nil { + glog.Infof("Ignoring Ingress %v(Minion): %v", ingress.Name, err) + return + } + glog.V(3).Infof("Removing Ingress: %v(Minion) for %v(Master)", ingress.Name, master.Name) + lbc.AddSyncQueue(master) + } else { + glog.V(3).Infof("Removing Ingress: %v", ingress.Name) + lbc.AddSyncQueue(obj) + } + }, + UpdateFunc: func(old, current interface{}) { + c := current.(*extensions.Ingress) + o := old.(*extensions.Ingress) + if !lbc.IsNginxIngress(c) { + return + } + if utils.HasChanges(o, c) { + glog.V(3).Infof("Ingress %v changed, syncing", c.Name) + lbc.AddSyncQueue(c) + } + }, + } +} diff --git a/internal/handlers/leader.go b/internal/handlers/leader.go new file mode 100644 index 0000000000..7f58fc9628 --- /dev/null +++ b/internal/handlers/leader.go @@ -0,0 +1,20 @@ +package handlers + +import ( + "github.com/golang/glog" + "github.com/nginxinc/kubernetes-ingress/internal/controller" + "k8s.io/client-go/tools/leaderelection" +) + +func CreateLeaderHandler(lbc *controller.LoadBalancerController) leaderelection.LeaderCallbacks { + return leaderelection.LeaderCallbacks{ + OnStartedLeading: func(stop <-chan struct{}) { + glog.V(3).Info("started leading, updating ingress status") + ingresses, mergeableIngresses := lbc.GetManagedIngresses() + err := lbc.UpdateManagedAndMergeableIngresses(ingresses, mergeableIngresses) + if err != nil { + glog.V(3).Infof("error updating status when starting leading: %v", err) + } + }, + } +} diff --git a/internal/handlers/secret.go b/internal/handlers/secret.go new file mode 100644 index 0000000000..4233c564fe --- /dev/null +++ b/internal/handlers/secret.go @@ -0,0 +1,59 @@ +package handlers + +import ( + "reflect" + + "github.com/golang/glog" + "github.com/nginxinc/kubernetes-ingress/internal/controller" + api_v1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/cache" +) + +func CreateSecretHandlers(lbc *controller.LoadBalancerController) cache.ResourceEventHandlerFuncs { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + secret := obj.(*api_v1.Secret) + if err := lbc.ValidateSecret(secret); err != nil { + return + } + nsname := secret.Namespace + "/" + secret.Name + if nsname == lbc.GetDefaultServerSecret() { + glog.V(3).Infof("Adding default server Secret: %v", secret.Name) + lbc.AddSyncQueue(obj) + } + }, + DeleteFunc: func(obj interface{}) { + secret, isSecr := obj.(*api_v1.Secret) + if !isSecr { + deletedState, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + glog.V(3).Infof("Error received unexpected object: %v", obj) + return + } + secret, ok = deletedState.Obj.(*api_v1.Secret) + if !ok { + glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Secret object: %v", deletedState.Obj) + return + } + } + if err := lbc.ValidateSecret(secret); err != nil { + return + } + + glog.V(3).Infof("Removing Secret: %v", secret.Name) + lbc.AddSyncQueue(obj) + }, + UpdateFunc: func(old, cur interface{}) { + errOld := lbc.ValidateSecret(old.(*api_v1.Secret)) + errCur := lbc.ValidateSecret(cur.(*api_v1.Secret)) + if errOld != nil && errCur != nil { + return + } + + if !reflect.DeepEqual(old, cur) { + glog.V(3).Infof("Secret %v changed, syncing", cur.(*api_v1.Secret).Name) + lbc.AddSyncQueue(cur) + } + }, + } +} diff --git a/internal/handlers/service.go b/internal/handlers/service.go new file mode 100644 index 0000000000..f371ce0c27 --- /dev/null +++ b/internal/handlers/service.go @@ -0,0 +1,59 @@ +package handlers + +import ( + "reflect" + + "github.com/golang/glog" + "github.com/nginxinc/kubernetes-ingress/internal/controller" + "k8s.io/client-go/tools/cache" + + api_v1 "k8s.io/api/core/v1" +) + +func CreateServiceHandlers(lbc *controller.LoadBalancerController) cache.ResourceEventHandlerFuncs { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + svc := obj.(*api_v1.Service) + if lbc.IsExternalServiceForStatus(svc) { + lbc.AddSyncQueue(svc) + return + } + glog.V(3).Infof("Adding service: %v", svc.Name) + lbc.EnqueueIngressForService(svc) + }, + DeleteFunc: func(obj interface{}) { + svc, isSvc := obj.(*api_v1.Service) + if !isSvc { + deletedState, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + glog.V(3).Infof("Error received unexpected object: %v", obj) + return + } + svc, ok = deletedState.Obj.(*api_v1.Service) + if !ok { + glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Service object: %v", deletedState.Obj) + return + } + } + if lbc.IsExternalServiceForStatus(svc) { + lbc.AddSyncQueue(svc) + return + } + + glog.V(3).Infof("Removing service: %v", svc.Name) + lbc.EnqueueIngressForService(svc) + + }, + UpdateFunc: func(old, cur interface{}) { + if !reflect.DeepEqual(old, cur) { + svc := cur.(*api_v1.Service) + if lbc.IsExternalServiceForStatus(svc) { + lbc.AddSyncQueue(svc) + return + } + glog.V(3).Infof("Service %v changed, syncing", svc.Name) + lbc.EnqueueIngressForService(svc) + } + }, + } +} diff --git a/internal/queue/queue.go b/internal/queue/queue.go new file mode 100644 index 0000000000..68f08ea461 --- /dev/null +++ b/internal/queue/queue.go @@ -0,0 +1,89 @@ +package queue + +import ( + "time" + + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" +) + +var keyFunc = cache.DeletionHandlingMetaNamespaceKeyFunc + +// TaskQueue manages a work queue through an independent worker that +// invokes the given sync function for every work item inserted. +type TaskQueue struct { + // queue is the work queue the worker polls + queue *workqueue.Type + // sync is called for each item in the queue + sync func(Task) + // workerDone is closed when the worker exits + workerDone chan struct{} +} + +// NewTaskQueue creates a new task queue with the given sync function. +// The sync function is called for every element inserted into the queue. +func NewTaskQueue(syncFn func(Task)) *TaskQueue { + return &TaskQueue{ + queue: workqueue.New(), + sync: syncFn, + workerDone: make(chan struct{}), + } +} + +func (t *TaskQueue) Run(period time.Duration, stopCh <-chan struct{}) { + wait.Until(t.worker, period, stopCh) +} + +// Enqueue enqueues ns/name of the given api object in the task queue. +func (t *TaskQueue) Enqueue(obj interface{}) { + key, err := keyFunc(obj) + if err != nil { + glog.V(3).Infof("Couldn't get key for object %v: %v", obj, err) + return + } + + task, err := NewTask(key, obj) + if err != nil { + glog.V(3).Infof("Couldn't create a task for object %v: %v", obj, err) + return + } + + glog.V(3).Infof("Adding an element with a key: %v", task.Key) + + t.queue.Add(task) +} + +func (t *TaskQueue) Requeue(task Task, err error) { + glog.Errorf("Requeuing %v, err %v", task.Key, err) + t.queue.Add(task) +} + +func (t *TaskQueue) RequeueAfter(task Task, err error, after time.Duration) { + glog.Errorf("Requeuing %v after %s, err %v", task.Key, after.String(), err) + go func(task Task, after time.Duration) { + time.Sleep(after) + t.queue.Add(task) + }(task, after) +} + +// worker processes work in the queue through sync. +func (t *TaskQueue) worker() { + for { + task, quit := t.queue.Get() + if quit { + close(t.workerDone) + return + } + glog.V(3).Infof("Syncing %v", task.(Task).Key) + t.sync(task.(Task)) + t.queue.Done(task) + } +} + +// shutdown shuts down the work queue and waits for the worker to ACK +func (t *TaskQueue) Shutdown() { + t.queue.ShutDown() + <-t.workerDone +} diff --git a/internal/queue/task.go b/internal/queue/task.go new file mode 100644 index 0000000000..7cf65931ce --- /dev/null +++ b/internal/queue/task.go @@ -0,0 +1,59 @@ +package queue + +import ( + "fmt" + + "github.com/nginxinc/kubernetes-ingress/internal/utils" + api_v1 "k8s.io/api/core/v1" + extensions "k8s.io/api/extensions/v1beta1" +) + +// Kind represents the kind of the Kubernetes resources of a task +type Kind int + +const ( + // Ingress resource + Ingress = iota + // IngressMinion resource, which is a Minion Ingress resource + IngressMinion + // Endpoints resource + Endpoints + // ConfigMap resource + ConfigMap + // Secret resource + Secret + // Service resource + Service +) + +// Task is an element of a TaskQueue +type Task struct { + Kind Kind + Key string +} + +// NewTask creates a new task +func NewTask(key string, obj interface{}) (Task, error) { + var k Kind + switch t := obj.(type) { + case *extensions.Ingress: + ing := obj.(*extensions.Ingress) + if utils.IsMinion(ing) { + k = IngressMinion + } else { + k = Ingress + } + case *api_v1.Endpoints: + k = Endpoints + case *api_v1.ConfigMap: + k = ConfigMap + case *api_v1.Secret: + k = Secret + case *api_v1.Service: + k = Service + default: + return Task{}, fmt.Errorf("Unknow type: %v", t) + } + + return Task{k, key}, nil +} diff --git a/internal/controller/utils.go b/internal/utils/utils.go similarity index 58% rename from internal/controller/utils.go rename to internal/utils/utils.go index 33f11ed359..6c3965382d 100644 --- a/internal/controller/utils.go +++ b/internal/utils/utils.go @@ -14,150 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controller +package utils import ( "fmt" - "time" + "reflect" + "strings" "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/workqueue" api_v1 "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" - - "github.com/golang/glog" -) - -// TaskQueue manages a work queue through an independent worker that -// invokes the given sync function for every work item inserted. -type TaskQueue struct { - // queue is the work queue the worker polls - queue *workqueue.Type - // sync is called for each item in the queue - sync func(Task) - // workerDone is closed when the worker exits - workerDone chan struct{} -} - -func (t *TaskQueue) run(period time.Duration, stopCh <-chan struct{}) { - wait.Until(t.worker, period, stopCh) -} - -// enqueue enqueues ns/name of the given api object in the task queue. -func (t *TaskQueue) enqueue(obj interface{}) { - key, err := keyFunc(obj) - if err != nil { - glog.V(3).Infof("Couldn't get key for object %v: %v", obj, err) - return - } - - task, err := NewTask(key, obj) - if err != nil { - glog.V(3).Infof("Couldn't create a task for object %v: %v", obj, err) - return - } - - glog.V(3).Infof("Adding an element with a key: %v", task.Key) - - t.queue.Add(task) -} - -func (t *TaskQueue) requeue(task Task, err error) { - glog.Errorf("Requeuing %v, err %v", task.Key, err) - t.queue.Add(task) -} - -func (t *TaskQueue) requeueAfter(task Task, err error, after time.Duration) { - glog.Errorf("Requeuing %v after %s, err %v", task.Key, after.String(), err) - go func(task Task, after time.Duration) { - time.Sleep(after) - t.queue.Add(task) - }(task, after) -} - -// worker processes work in the queue through sync. -func (t *TaskQueue) worker() { - for { - task, quit := t.queue.Get() - if quit { - close(t.workerDone) - return - } - glog.V(3).Infof("Syncing %v", task.(Task).Key) - t.sync(task.(Task)) - t.queue.Done(task) - } -} - -// shutdown shuts down the work queue and waits for the worker to ACK -func (t *TaskQueue) shutdown() { - t.queue.ShutDown() - <-t.workerDone -} - -// NewTaskQueue creates a new task queue with the given sync function. -// The sync function is called for every element inserted into the queue. -func NewTaskQueue(syncFn func(Task)) *TaskQueue { - return &TaskQueue{ - queue: workqueue.New(), - sync: syncFn, - workerDone: make(chan struct{}), - } -} - -// Kind represents the kind of the Kubernetes resources of a task -type Kind int - -const ( - // Ingress resource - Ingress = iota - // IngressMinion resource, which is a Minion Ingress resource - IngressMinion - // Endpoints resource - Endpoints - // ConfigMap resource - ConfigMap - // Secret resource - Secret - // Service resource - Service ) -// Task is an element of a TaskQueue -type Task struct { - Kind Kind - Key string -} - -// NewTask creates a new task -func NewTask(key string, obj interface{}) (Task, error) { - var k Kind - switch t := obj.(type) { - case *extensions.Ingress: - ing := obj.(*extensions.Ingress) - if isMinion(ing) { - k = IngressMinion - } else { - k = Ingress - } - case *api_v1.Endpoints: - k = Endpoints - case *api_v1.ConfigMap: - k = ConfigMap - case *api_v1.Secret: - k = Secret - case *api_v1.Service: - k = Service - default: - return Task{}, fmt.Errorf("Unknow type: %v", t) - } - - return Task{k, key}, nil -} - // compareLinks returns true if the 2 self links are equal. func compareLinks(l1, l2 string) bool { // TODO: These can be partial links @@ -276,3 +146,33 @@ func FindPort(pod *api_v1.Pod, svcPort *api_v1.ServicePort) (int32, error) { type StoreToSecretLister struct { cache.Store } + +func IsMinion(ing *extensions.Ingress) bool { + if ing.Annotations["nginx.org/mergeable-ingress-type"] == "minion" { + return true + } + return false +} + +func IsMaster(ing *extensions.Ingress) bool { + if ing.Annotations["nginx.org/mergeable-ingress-type"] == "master" { + return true + } + return false +} + +func HasChanges(old *extensions.Ingress, current *extensions.Ingress) bool { + old.Status.LoadBalancer.Ingress = current.Status.LoadBalancer.Ingress + old.ResourceVersion = current.ResourceVersion + return !reflect.DeepEqual(old, current) +} + +// ParseNamespaceName parses the string in the / format and returns the name and the namespace. +// It returns an error in case the string does not follow the / format. +func ParseNamespaceName(value string) (ns string, name string, err error) { + res := strings.Split(value, "/") + if len(res) != 2 { + return "", "", fmt.Errorf("%q must follow the format /", value) + } + return res[0], res[1], nil +} From 39b13387139b94b3fddeebeda6de2f4ce1dc3262 Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Wed, 5 Sep 2018 11:15:16 +0100 Subject: [PATCH 06/10] Fix failing tests from renaming --- cmd/{nginx-ic => nginx-ingress}/main_test.go | 0 internal/controller/controller_test.go | 18 +++++++++--------- internal/controller/status_test.go | 3 ++- 3 files changed, 11 insertions(+), 10 deletions(-) rename cmd/{nginx-ic => nginx-ingress}/main_test.go (100%) diff --git a/cmd/nginx-ic/main_test.go b/cmd/nginx-ingress/main_test.go similarity index 100% rename from cmd/nginx-ic/main_test.go rename to cmd/nginx-ingress/main_test.go diff --git a/internal/controller/controller_test.go b/internal/controller/controller_test.go index 665c5db487..ecb282a8b2 100644 --- a/internal/controller/controller_test.go +++ b/internal/controller/controller_test.go @@ -133,23 +133,23 @@ func TestIsNginxIngress(t *testing.T) { } for _, test := range testsWithoutIngressClassOnly { - if result := test.lbc.isNginxIngress(test.ing); result != test.expected { + if result := test.lbc.IsNginxIngress(test.ing); result != test.expected { classAnnotation := "N/A" if class, exists := test.ing.Annotations[ingressClassKey]; exists { classAnnotation = class } - t.Errorf("lbc.isNginxIngress(ing), lbc.ingressClass=%v, lbc.useIngressClassOnly=%v, ing.Annotations['%v']=%v; got %v, expected %v", + t.Errorf("lbc.IsNginxIngress(ing), lbc.ingressClass=%v, lbc.useIngressClassOnly=%v, ing.Annotations['%v']=%v; got %v, expected %v", test.lbc.ingressClass, test.lbc.useIngressClassOnly, ingressClassKey, classAnnotation, result, test.expected) } } for _, test := range testsWithIngressClassOnly { - if result := test.lbc.isNginxIngress(test.ing); result != test.expected { + if result := test.lbc.IsNginxIngress(test.ing); result != test.expected { classAnnotation := "N/A" if class, exists := test.ing.Annotations[ingressClassKey]; exists { classAnnotation = class } - t.Errorf("lbc.isNginxIngress(ing), lbc.ingressClass=%v, lbc.useIngressClassOnly=%v, ing.Annotations['%v']=%v; got %v, expected %v", + t.Errorf("lbc.IsNginxIngress(ing), lbc.ingressClass=%v, lbc.useIngressClassOnly=%v, ing.Annotations['%v']=%v; got %v, expected %v", test.lbc.ingressClass, test.lbc.useIngressClassOnly, ingressClassKey, classAnnotation, result, test.expected) } } @@ -241,7 +241,7 @@ func TestFindMasterForMinion(t *testing.T) { lbc.ingressLister.Add(&coffeeMinion) lbc.ingressLister.Add(&teaMinion) - master, err := lbc.findMasterForMinion(&coffeeMinion) + master, err := lbc.FindMasterForMinion(&coffeeMinion) if err != nil { t.Errorf("Error finding master for %s(Minion): %v", coffeeMinion.Name, err) } @@ -249,7 +249,7 @@ func TestFindMasterForMinion(t *testing.T) { t.Errorf("Invalid Master found. Obtained %+v, Expected %+v", master, cafeMaster) } - master, err = lbc.findMasterForMinion(&teaMinion) + master, err = lbc.FindMasterForMinion(&teaMinion) if err != nil { t.Errorf("Error finding master for %s(Minion): %v", teaMinion.Name, err) } @@ -265,13 +265,13 @@ func TestFindMasterForMinionNoMaster(t *testing.T) { lbc.ingressLister.Add(&teaMinion) expected := fmt.Errorf("Could not find a Master for Minion: '%v/%v'", coffeeMinion.Namespace, coffeeMinion.Name) - _, err := lbc.findMasterForMinion(&coffeeMinion) + _, err := lbc.FindMasterForMinion(&coffeeMinion) if !reflect.DeepEqual(err, expected) { t.Errorf("Expected: %s \nObtained: %s", expected, err) } expected = fmt.Errorf("Could not find a Master for Minion: '%v/%v'", teaMinion.Namespace, teaMinion.Name) - _, err = lbc.findMasterForMinion(&teaMinion) + _, err = lbc.FindMasterForMinion(&teaMinion) if !reflect.DeepEqual(err, expected) { t.Errorf("Error master found for %s(Minion): %v", teaMinion.Name, err) } @@ -294,7 +294,7 @@ func TestFindMasterForMinionInvalidMinion(t *testing.T) { lbc.ingressLister.Add(&cafeMaster) lbc.ingressLister.Add(&coffeeMinion) - master, err := lbc.findMasterForMinion(&coffeeMinion) + master, err := lbc.FindMasterForMinion(&coffeeMinion) if err != nil { t.Errorf("Error finding master for %s(Minion): %v", coffeeMinion.Name, err) } diff --git a/internal/controller/status_test.go b/internal/controller/status_test.go index defee77b89..f6583503da 100644 --- a/internal/controller/status_test.go +++ b/internal/controller/status_test.go @@ -3,6 +3,7 @@ package controller import ( "testing" + "github.com/nginxinc/kubernetes-ingress/internal/utils" "k8s.io/api/core/v1" extensions "k8s.io/api/extensions/v1beta1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -32,7 +33,7 @@ func TestStatusUpdate(t *testing.T) { ing, }}, ) - ingLister := StoreToIngressLister{} + ingLister := utils.StoreToIngressLister{} ingLister.Store, _ = cache.NewInformer( cache.NewListWatchFromClient(fakeClient.Extensions().RESTClient(), "ingresses", "nginx-ingress", fields.Everything()), &extensions.Ingress{}, 2, nil) From bc7eebd15d9e492c3b51e8a32dc257909d4df4bf Mon Sep 17 00:00:00 2001 From: ismael_serrano Date: Wed, 5 Sep 2018 11:22:20 +0100 Subject: [PATCH 07/10] Change build location when not building in container --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f8633bad11..65225cb526 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ nginx-ingress: ifeq ($(BUILD_IN_CONTAINER),1) $(DOCKER_BUILD_RUN) -e CGO_ENABLED=0 $(GOLANG_CONTAINER) go build -a -installsuffix cgo -ldflags "-w -X main.version=${VERSION} -X main.gitCommit=${GIT_COMMIT}" -o /go/src/github.com/nginxinc/kubernetes-ingress/nginx-ingress else - CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags "-w -X main.version=${VERSION} -X main.gitCommit=${GIT_COMMIT}" -o nginx-ingress + CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags "-w -X main.version=${VERSION} -X main.gitCommit=${GIT_COMMIT}" -o nginx-ingress github.com/nginxinc/kubernetes-ingress/cmd/nginx-ingress endif test: From f12960e8ff020e7989410258a324f0ddd7f41291 Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Thu, 6 Sep 2018 14:25:22 +0100 Subject: [PATCH 08/10] Address PR feedback - lint, doc updates, dockerfiles and moving files. - Addresses all `golint` warnings including ones not caused by this PR - Moves install files to correct place - Updates docs with old references before structure - Fixes broken links (not caused by this PR) - Updates COPY command in other Dockerfiles --- .gitignore | 2 +- CONTRIBUTING.md | 2 +- README.md | 2 +- build/DockerfileForAlpine | 2 +- build/DockerfileForPlus | 2 +- build/README.md | 7 +--- cmd/nginx-ingress/main.go | 2 +- .../nginx-ingress-with-prometheus.yaml | 1 - .../nginx-ingress-with-prometheus.yaml | 1 - deployments/helm-chart/Chart.yaml | 2 +- deployments/helm-chart/README.md | 8 ++--- docs/installation.md | 2 +- examples/customization/README.md | 4 +-- internal/controller/controller.go | 14 +++++++- internal/controller/controller_test.go | 4 +-- internal/handlers/configMap.go | 1 + internal/handlers/endpoint.go | 1 + internal/handlers/ingress.go | 1 + internal/handlers/leader.go | 1 + internal/handlers/secret.go | 1 + internal/handlers/service.go | 1 + internal/nginx/configurator.go | 14 ++++---- internal/nginx/ingress.go | 1 + internal/nginx/nginx.go | 34 +++++++++---------- internal/nginx/plus/nginx_api.go | 4 +++ internal/nginx/plus/nginx_client.go | 1 + internal/nginx/template_executor.go | 2 +- internal/nginx/templates/templates_test.go | 2 +- internal/queue/queue.go | 7 ++-- internal/utils/utils.go | 3 ++ 30 files changed, 74 insertions(+), 55 deletions(-) rename {install => deployments}/daemon-set/nginx-ingress-with-prometheus.yaml (99%) rename {install => deployments}/deployment/nginx-ingress-with-prometheus.yaml (99%) diff --git a/.gitignore b/.gitignore index 820e61d81b..bf36da9b5b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,7 @@ nginx-ingress !nginx-ingress/ osx-nginx-plus-ingress nginx-plus-ingress -cmd/nginx-ic/nginx-ic +cmd/nginx-ingress/nginx-ingress # NGINX Plus license files *.crt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 67580f866b..7a43e2303e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ Read the [documentation](https://github.com/nginxinc/kubernetes-ingress/tree/mas * This Ingress Controller is written in Go and supports both the open source NGINX software and NGINX Plus. * The project follows a standard Go project layout - * The main code is found at `cmd/nginx-ic/` + * The main code is found at `cmd/nginx-ingress/` * The internal code is found at `internal/` * Build files for Docker and CI are found under `build/` * Deployment yaml files, and Helm files are found at `deployments/` diff --git a/README.md b/README.md index 2163120961..c8b70722dd 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ The table below summarizes the options regarding the images, manifests, helm cha | Version | Description | Image for NGINX | Image for NGINX Plus | Installation Manifests and Helm Chart | Documentation and Examples | | ------- | ----------- | --------------- | -------------------- | ---------------------------------------| -------------------------- | | Latest stable release | For production use | `nginx/nginx-ingress:1.3.0`, `nginx/nginx-ingress:1.3.0-alpine` from [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/) or [build your own image](https://github.com/nginxinc/kubernetes-ingress/tree/v1.3.0/nginx-controller). | [Build your own image](https://github.com/nginxinc/kubernetes-ingress/tree/v1.3.0/nginx-controller). | [Manifests](https://github.com/nginxinc/kubernetes-ingress/tree/v1.3.0/install). [Helm chart](https://github.com/nginxinc/kubernetes-ingress/tree/v1.3.0/helm-chart). | [Documentation](https://github.com/nginxinc/kubernetes-ingress/tree/v1.3.0/docs). [Examples](https://github.com/nginxinc/kubernetes-ingress/tree/v1.3.0/examples). | -| Edge | For testing and experimenting | `nginx/nginx-ingress:edge`, `nginx/nginx-ingress:edge-alpine` from [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/) or [build your own image](https://github.com/nginxinc/kubernetes-ingress/tree/master/nginx-controller). | [Build your own image](https://github.com/nginxinc/kubernetes-ingress/tree/master/nginx-controller). | [Manifests](https://github.com/nginxinc/kubernetes-ingress/tree/master/install). [Helm chart](https://github.com/nginxinc/kubernetes-ingress/tree/master/helm-chart). | [Documentation](https://github.com/nginxinc/kubernetes-ingress/tree/master/docs). [Examples](https://github.com/nginxinc/kubernetes-ingress/tree/master/examples). | +| Edge | For testing and experimenting | `nginx/nginx-ingress:edge`, `nginx/nginx-ingress:edge-alpine` from [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/) or [build your own image](https://github.com/nginxinc/kubernetes-ingress/tree/master/build). | [Build your own image](https://github.com/nginxinc/kubernetes-ingress/tree/master/build). | [Manifests](https://github.com/nginxinc/kubernetes-ingress/tree/master/deployments). [Helm chart](https://github.com/nginxinc/kubernetes-ingress/tree/master/deployments/helm-chart). | [Documentation](https://github.com/nginxinc/kubernetes-ingress/tree/master/docs). [Examples](https://github.com/nginxinc/kubernetes-ingress/tree/master/examples). | ## Benefits of Using the Ingress Controller with NGINX Plus diff --git a/build/DockerfileForAlpine b/build/DockerfileForAlpine index 08e44b88c7..9f8a5be296 100644 --- a/build/DockerfileForAlpine +++ b/build/DockerfileForAlpine @@ -6,7 +6,7 @@ RUN ln -sf /proc/1/fd/1 /var/log/nginx/access.log \ && ln -sf /proc/1/fd/1 /var/log/nginx/stream-access.log \ && ln -sf /proc/1/fd/2 /var/log/nginx/error.log -COPY nginx-ingress nginx/templates/nginx.ingress.tmpl nginx/templates/nginx.tmpl / +COPY nginx-ingress internal/nginx/templates/nginx.ingress.tmpl internal/nginx/templates/nginx.tmpl / RUN rm /etc/nginx/conf.d/* diff --git a/build/DockerfileForPlus b/build/DockerfileForPlus index 3e8530bdce..aed325e074 100644 --- a/build/DockerfileForPlus +++ b/build/DockerfileForPlus @@ -50,7 +50,7 @@ RUN ln -sf /proc/1/fd/1 /var/log/nginx/access.log \ EXPOSE 80 443 -COPY nginx-ingress nginx/templates/nginx-plus.ingress.tmpl nginx/templates/nginx-plus.tmpl / +COPY nginx-ingress internal/nginx/templates/nginx-plus.ingress.tmpl internal/nginx/templates/nginx-plus.tmpl / RUN rm /etc/nginx/conf.d/* \ && mkdir -p /etc/nginx/secrets diff --git a/build/README.md b/build/README.md index 82b3c3efc2..907cd522ae 100644 --- a/build/README.md +++ b/build/README.md @@ -32,11 +32,6 @@ We build the image using the make utility and the provided `Makefile`. Let’s c $ git clone https://github.com/nginxinc/kubernetes-ingress/ ``` -1. If you're using a stable release, check out the corresponding tag. For release 1.3.0, run: - ``` - $ git checkout v1.3.0 - ``` - 1. Build the image: * For NGINX: ``` @@ -47,7 +42,7 @@ We build the image using the make utility and the provided `Makefile`. Let’s c As the result, the image **myregistry.example.com/nginx-ingress:edge** is built and pushed to the registry. Note that the tag `edge` comes from the `VERSION` variable, defined in the Makefile. - * For NGINX Plus, first, make sure that the certificate (`nginx-repo.crt`) and the key (`nginx-repo.key`) of your license are located in the `nginx-controller` folder: + * For NGINX Plus, first, make sure that the certificate (`nginx-repo.crt`) and the key (`nginx-repo.key`) of your license are located in the root of the project: ``` $ ls nginx-repo.* nginx-repo.crt nginx-repo.key diff --git a/cmd/nginx-ingress/main.go b/cmd/nginx-ingress/main.go index b8545c0f29..5bbbafa191 100644 --- a/cmd/nginx-ingress/main.go +++ b/cmd/nginx-ingress/main.go @@ -284,7 +284,7 @@ func main() { } } -func handleTermination(lbc *controller.LoadBalancerController, ngxc *nginx.NginxController, nginxDone chan error) { +func handleTermination(lbc *controller.LoadBalancerController, ngxc *nginx.Controller, nginxDone chan error) { signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, syscall.SIGTERM) diff --git a/install/daemon-set/nginx-ingress-with-prometheus.yaml b/deployments/daemon-set/nginx-ingress-with-prometheus.yaml similarity index 99% rename from install/daemon-set/nginx-ingress-with-prometheus.yaml rename to deployments/daemon-set/nginx-ingress-with-prometheus.yaml index eabaf93a0a..92398cc9ff 100644 --- a/install/daemon-set/nginx-ingress-with-prometheus.yaml +++ b/deployments/daemon-set/nginx-ingress-with-prometheus.yaml @@ -52,4 +52,3 @@ spec: - :9113 - -nginx.scrape-uri - http://127.0.0.1:8080/stub_status - diff --git a/install/deployment/nginx-ingress-with-prometheus.yaml b/deployments/deployment/nginx-ingress-with-prometheus.yaml similarity index 99% rename from install/deployment/nginx-ingress-with-prometheus.yaml rename to deployments/deployment/nginx-ingress-with-prometheus.yaml index 051d5b660c..a77d0d6ee9 100644 --- a/install/deployment/nginx-ingress-with-prometheus.yaml +++ b/deployments/deployment/nginx-ingress-with-prometheus.yaml @@ -51,4 +51,3 @@ spec: - :9113 - nginx.scrape-uri - http://127.0.0.1:8080/stub_status - diff --git a/deployments/helm-chart/Chart.yaml b/deployments/helm-chart/Chart.yaml index 05f8be4cfc..f62e788fed 100644 --- a/deployments/helm-chart/Chart.yaml +++ b/deployments/helm-chart/Chart.yaml @@ -3,7 +3,7 @@ version: 0.1.2 appVersion: edge description: NGINX Ingress Controller sources: - - https://github.com/nginxinc/kubernetes-ingress/tree/master/helm-chart + - https://github.com/nginxinc/kubernetes-ingress/tree/master/deployment/helm-chart keywords: - ingress - nginx diff --git a/deployments/helm-chart/README.md b/deployments/helm-chart/README.md index fdf82847c3..3baa696460 100644 --- a/deployments/helm-chart/README.md +++ b/deployments/helm-chart/README.md @@ -19,13 +19,9 @@ This chart deploys the NGINX Ingress controller in your Kubernetes cluster. ``` $ git clone https://github.com/nginxinc/kubernetes-ingress/ ``` -1. If you're using a stable release, check out the corresponding tag. For release 1.3.0, run: +2. Change your working directory to /deployments/helm-chart: ``` - $ git checkout v1.3.0 - ``` -2. Change your working directory to /helm-chart: - ``` - $ cd kubernetes-ingress/helm-chart + $ cd kubernetes-ingress/deployments/helm-chart ``` 3. To install the chart with the release name my-release (my-release is the name that you choose): diff --git a/docs/installation.md b/docs/installation.md index 7058e0e099..9df112bee0 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -7,7 +7,7 @@ Make sure you have access to the Ingress controller image: * For NGINX Ingress controller, use the image `nginx/nginx-ingress` from [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/). * For NGINX Plus Ingress controller, build your own image and push it to your private Docker registry by following the instructions from [here](../build/README.md). -The installation manifests are located in the [install](../install) folder. In the steps below we assume that you will be running the commands from that folder. +The installation manifests are located in the [deployments](../deployments) folder. In the steps below we assume that you will be running the commands from that folder. ## 1. Create a Namespace, a SA and the Default Secret. diff --git a/examples/customization/README.md b/examples/customization/README.md index f204f9846c..e38a046389 100644 --- a/examples/customization/README.md +++ b/examples/customization/README.md @@ -24,7 +24,7 @@ The table below summarizes all of the options. For some of them, there are examp | `nginx.org/redirect-to-https` | `redirect-to-https` | Sets the 301 redirect rule based on the value of the `http_x_forwarded_proto` header on the server block to force incoming traffic to be over HTTPS. Useful when terminating SSL in a load balancer in front of the Ingress controller — see [115](https://github.com/nginxinc/kubernetes-ingress/issues/115) | `False` | | | `ingress.kubernetes.io/ssl-redirect` | `ssl-redirect` | Sets an unconditional 301 redirect rule for all incoming HTTP traffic to force incoming traffic over HTTPS. | `True` | | | N/A | `error-log-level` | Sets the global [error log level](http://nginx.org/en/docs/ngx_core_module.html#error_log) for NGINX. | `notice` | | -| N/A | `log-format` | Sets the custom [log format](http://nginx.org/en/docs/http/ngx_http_log_module.html#log_format). | See the [template file](../../nginx-controller/nginx/nginx.conf.tmpl). | | +| N/A | `log-format` | Sets the custom [log format](http://nginx.org/en/docs/http/ngx_http_log_module.html#log_format). | See the [template file](../../internal/nginx/templates/nginx.tmpl). | | | `nginx.org/hsts` | `hsts` | Enables [HTTP Strict Transport Security (HSTS)](https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/): the HSTS header is added to the responses from backends. The `preload` directive is included in the header. | `False` | | | `nginx.org/hsts-max-age` | `hsts-max-age` | Sets the value of the `max-age` directive of the HSTS header. | `2592000` (1 month) | | `nginx.org/hsts-include-subdomains` | `hsts-include-subdomains` | Adds the `includeSubDomains` directive to the HSTS header. | `False`| | @@ -69,7 +69,7 @@ The table below summarizes all of the options. For some of them, there are examp | `nginx.com/slow-start` | N/A | Sets the upstream server [slow-start period](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#server-slow-start). By default, slow-start is activated after a server becomes [available](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/#passive-health-checks) or [healthy](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/#active-health-checks). To enable slow-start for newly added servers, configure [mandatory active health checks](../health-checks). | `"0s"` | | | N/A | `external-status-address` | Sets the address to be reported in the status of Ingress resources. Requires the `-report-status` command-line argument. Overrides the `-external-service` argument. | N/A | [Report Ingress Status](../../docs/report-ingress-status.md). | | N/A | `stream-snippets` | Sets a custom snippet in stream context. | N/A | [Support for TCP/UDP Load Balancing](../tcp-udp). | -| N/A | `stream-log-format` | Sets the custom [log format](http://nginx.org/en/docs/stream/ngx_stream_log_module.html#log_format) for TCP/UDP load balancing. | See the [template file](../../nginx-controller/nginx/nginx.conf.tmpl). | | +| N/A | `stream-log-format` | Sets the custom [log format](http://nginx.org/en/docs/stream/ngx_stream_log_module.html#log_format) for TCP/UDP load balancing. | See the [template file](../../internal/nginx/templates/nginx.tmpl). | | ## Using ConfigMaps diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 0f77f40c08..8882679380 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -137,10 +137,12 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc return &lbc } +// UpdateManagedAndMergeableIngresses invokes the UpdateManagedAndMergeableIngresses method on the Status Updater func (lbc *LoadBalancerController) UpdateManagedAndMergeableIngresses(ingresses []v1beta1.Ingress, mergeableIngresses map[string]*nginx.MergeableIngresses) error { return lbc.statusUpdater.UpdateManagedAndMergeableIngresses(ingresses, mergeableIngresses) } +// AddLeaderHandler adds the handler for leader election to the controller func (lbc *LoadBalancerController) AddLeaderHandler(leaderHandler leaderelection.LeaderCallbacks) { var err error lbc.leaderElector, err = NewLeaderElector(lbc.client, leaderHandler, lbc.controllerNamespace) @@ -149,18 +151,22 @@ func (lbc *LoadBalancerController) AddLeaderHandler(leaderHandler leaderelection } } +// GetIngressClassKey returns the ingress class key func (lbc *LoadBalancerController) GetIngressClassKey() string { return ingressClassKey } +// AddSyncQueue enqueues the provided item on the sync queue func (lbc *LoadBalancerController) AddSyncQueue(item interface{}) { lbc.syncQueue.Enqueue(item) } +// WatchNginxConfigMaps sets the controller to watch config map changes func (lbc *LoadBalancerController) WatchNginxConfigMaps() { lbc.watchNginxConfigMaps = true } +// AddSecretHandler adds the handler for secrets to the controller func (lbc *LoadBalancerController) AddSecretHandler(handlers cache.ResourceEventHandlerFuncs) { lbc.secretLister.Store, lbc.secretController = cache.NewInformer( cache.NewListWatchFromClient( @@ -174,6 +180,7 @@ func (lbc *LoadBalancerController) AddSecretHandler(handlers cache.ResourceEvent ) } +// AddServiceHandler adds the handler for services to the controller func (lbc *LoadBalancerController) AddServiceHandler(handlers cache.ResourceEventHandlerFuncs) { lbc.svcLister, lbc.svcController = cache.NewInformer( cache.NewListWatchFromClient( @@ -187,6 +194,7 @@ func (lbc *LoadBalancerController) AddServiceHandler(handlers cache.ResourceEven ) } +// AddIngressHandler adds the handler for ingresses to the controller func (lbc *LoadBalancerController) AddIngressHandler(handlers cache.ResourceEventHandlerFuncs) { lbc.ingressLister.Store, lbc.ingressController = cache.NewInformer( cache.NewListWatchFromClient( @@ -200,6 +208,7 @@ func (lbc *LoadBalancerController) AddIngressHandler(handlers cache.ResourceEven ) } +// AddEndpointHandler adds the handler for endpoints to the controller func (lbc *LoadBalancerController) AddEndpointHandler(handlers cache.ResourceEventHandlerFuncs) { lbc.endpointLister.Store, lbc.endpointController = cache.NewInformer( cache.NewListWatchFromClient( @@ -213,6 +222,7 @@ func (lbc *LoadBalancerController) AddEndpointHandler(handlers cache.ResourceEve ) } +// AddConfigMapHandler adds the handler for config maps to the controller func (lbc *LoadBalancerController) AddConfigMapHandler(handlers cache.ResourceEventHandlerFuncs, namespace string) { lbc.configMapLister.Store, lbc.configMapController = cache.NewInformer( cache.NewListWatchFromClient( @@ -226,6 +236,7 @@ func (lbc *LoadBalancerController) AddConfigMapHandler(handlers cache.ResourceEv ) } +// GetDefaultServerSecret returns the default server secret func (lbc *LoadBalancerController) GetDefaultServerSecret() string { return lbc.defaultServerSecret } @@ -579,7 +590,7 @@ func (lbc *LoadBalancerController) syncExternalService(task queue.Task) { } } -// isExternalServiceForStatus matches the service specified by the external-service arg +// IsExternalServiceForStatus matches the service specified by the external-service arg func (lbc *LoadBalancerController) IsExternalServiceForStatus(svc *api_v1.Service) bool { return lbc.statusUpdater.namespace == svc.Namespace && lbc.statusUpdater.externalServiceName == svc.Name } @@ -805,6 +816,7 @@ items: return nonMinions, minions, nil } +// EnqueueIngressForService enqueues the ingress for the given service func (lbc *LoadBalancerController) EnqueueIngressForService(svc *api_v1.Service) { ings := lbc.getIngressesForService(svc) for _, ing := range ings { diff --git a/internal/controller/controller_test.go b/internal/controller/controller_test.go index ecb282a8b2..e406af7a19 100644 --- a/internal/controller/controller_test.go +++ b/internal/controller/controller_test.go @@ -549,7 +549,7 @@ func getMergableDefaults() (cafeMaster, coffeeMinion, teaMinion extensions.Ingre cafeMasterIngEx, _ := lbc.createIngress(&cafeMaster) ingExMap["default-cafe-master"] = cafeMasterIngEx - cnf := nginx.NewConfigurator(&nginx.NginxController{}, &nginx.Config{}, &plus.NginxAPIController{}, &nginx.TemplateExecutor{}) + cnf := nginx.NewConfigurator(&nginx.Controller{}, &nginx.Config{}, &plus.NginxAPIController{}, &nginx.TemplateExecutor{}) // edit private field ingresses to use in testing pointerVal := reflect.ValueOf(cnf) @@ -782,7 +782,7 @@ func TestFindProbeForPods(t *testing.T) { func TestGetServicePortForIngressPort(t *testing.T) { fakeClient := fake.NewSimpleClientset() - cnf := nginx.NewConfigurator(&nginx.NginxController{}, &nginx.Config{}, &plus.NginxAPIController{}, &nginx.TemplateExecutor{}) + cnf := nginx.NewConfigurator(&nginx.Controller{}, &nginx.Config{}, &plus.NginxAPIController{}, &nginx.TemplateExecutor{}) lbc := LoadBalancerController{ client: fakeClient, ingressClass: "nginx", diff --git a/internal/handlers/configMap.go b/internal/handlers/configMap.go index 93cbc077a8..9a61672848 100644 --- a/internal/handlers/configMap.go +++ b/internal/handlers/configMap.go @@ -9,6 +9,7 @@ import ( "k8s.io/client-go/tools/cache" ) +// CreateConfigMapHandlers builds the handler funcs for config maps func CreateConfigMapHandlers(lbc *controller.LoadBalancerController, name string) cache.ResourceEventHandlerFuncs { return cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { diff --git a/internal/handlers/endpoint.go b/internal/handlers/endpoint.go index 8186613204..12e8d5aa18 100644 --- a/internal/handlers/endpoint.go +++ b/internal/handlers/endpoint.go @@ -9,6 +9,7 @@ import ( "k8s.io/client-go/tools/cache" ) +// CreateEndpointHandlers builds the handler funcs for endpoints func CreateEndpointHandlers(lbc *controller.LoadBalancerController) cache.ResourceEventHandlerFuncs { return cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { diff --git a/internal/handlers/ingress.go b/internal/handlers/ingress.go index 50fe681128..6c2ec394e7 100644 --- a/internal/handlers/ingress.go +++ b/internal/handlers/ingress.go @@ -8,6 +8,7 @@ import ( "k8s.io/client-go/tools/cache" ) +// CreateIngressHandlers builds the handler funcs for ingresses func CreateIngressHandlers(lbc *controller.LoadBalancerController) cache.ResourceEventHandlerFuncs { return cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { diff --git a/internal/handlers/leader.go b/internal/handlers/leader.go index 7f58fc9628..b60e1ba5ea 100644 --- a/internal/handlers/leader.go +++ b/internal/handlers/leader.go @@ -6,6 +6,7 @@ import ( "k8s.io/client-go/tools/leaderelection" ) +// CreateLeaderHandler builds the handler funcs for leader handling func CreateLeaderHandler(lbc *controller.LoadBalancerController) leaderelection.LeaderCallbacks { return leaderelection.LeaderCallbacks{ OnStartedLeading: func(stop <-chan struct{}) { diff --git a/internal/handlers/secret.go b/internal/handlers/secret.go index 4233c564fe..b0972ff727 100644 --- a/internal/handlers/secret.go +++ b/internal/handlers/secret.go @@ -9,6 +9,7 @@ import ( "k8s.io/client-go/tools/cache" ) +// CreateSecretHandlers builds the handler funcs for secrets func CreateSecretHandlers(lbc *controller.LoadBalancerController) cache.ResourceEventHandlerFuncs { return cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { diff --git a/internal/handlers/service.go b/internal/handlers/service.go index f371ce0c27..1e43e9890e 100644 --- a/internal/handlers/service.go +++ b/internal/handlers/service.go @@ -10,6 +10,7 @@ import ( api_v1 "k8s.io/api/core/v1" ) +// CreateServiceHandlers builds the handler funcs for services func CreateServiceHandlers(lbc *controller.LoadBalancerController) cache.ResourceEventHandlerFuncs { return cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { diff --git a/internal/nginx/configurator.go b/internal/nginx/configurator.go index 8a72d79822..c53fe18002 100644 --- a/internal/nginx/configurator.go +++ b/internal/nginx/configurator.go @@ -28,7 +28,7 @@ const JWTKeyAnnotation = "nginx.com/jwt-key" // Configurator transforms an Ingress resource into NGINX Configuration type Configurator struct { - nginx *NginxController + nginx *Controller config *Config nginxAPI *plus.NginxAPIController templateExecutor *TemplateExecutor @@ -37,7 +37,7 @@ type Configurator struct { } // NewConfigurator creates a new Configurator -func NewConfigurator(nginx *NginxController, config *Config, nginxAPI *plus.NginxAPIController, templateExecutor *TemplateExecutor) *Configurator { +func NewConfigurator(nginx *Controller, config *Config, nginxAPI *plus.NginxAPIController, templateExecutor *TemplateExecutor) *Configurator { cnf := Configurator{ nginx: nginx, config: config, @@ -738,7 +738,7 @@ func parsePort(value string) (int, error) { port, err := strconv.ParseInt(value, 10, 16) if err != nil { return 0, fmt.Errorf( - "Unable to parse port as integer: %s\n", + "Unable to parse port as integer: %s", err, ) } @@ -1051,7 +1051,7 @@ func (cnf *Configurator) updatePlusEndpoints(ingEx *IngressEx) error { func filterMasterAnnotations(annotations map[string]string) []string { var removedAnnotations []string - for key, _ := range annotations { + for key := range annotations { if _, notAllowed := masterBlacklist[key]; notAllowed { removedAnnotations = append(removedAnnotations, key) delete(annotations, key) @@ -1064,7 +1064,7 @@ func filterMasterAnnotations(annotations map[string]string) []string { func filterMinionAnnotations(annotations map[string]string) []string { var removedAnnotations []string - for key, _ := range annotations { + for key := range annotations { if _, notAllowed := minionBlacklist[key]; notAllowed { removedAnnotations = append(removedAnnotations, key) delete(annotations, key) @@ -1085,8 +1085,8 @@ func mergeMasterAnnotationsIntoMinion(minionAnnotations map[string]string, maste } // GenerateNginxMainConfig generate NginxMainConfig from Config -func GenerateNginxMainConfig(config *Config) *NginxMainConfig { - nginxCfg := &NginxMainConfig{ +func GenerateNginxMainConfig(config *Config) *MainConfig { + nginxCfg := &MainConfig{ MainSnippets: config.MainMainSnippets, HTTPSnippets: config.MainHTTPSnippets, StreamSnippets: config.MainStreamSnippets, diff --git a/internal/nginx/ingress.go b/internal/nginx/ingress.go index 1df62bcc7b..12c4bb2c8e 100644 --- a/internal/nginx/ingress.go +++ b/internal/nginx/ingress.go @@ -15,6 +15,7 @@ type IngressEx struct { HealthChecks map[string]*api_v1.Probe } +// MergeableIngresses is a mergeable ingress of a master and minions type MergeableIngresses struct { Master *IngressEx Minions []*IngressEx diff --git a/internal/nginx/nginx.go b/internal/nginx/nginx.go index 4fd6a2af08..8bc642c722 100644 --- a/internal/nginx/nginx.go +++ b/internal/nginx/nginx.go @@ -17,8 +17,8 @@ const dhparamFilename = "dhparam.pem" const TLSSecretFileMode = 0600 const jwkSecretFileMode = 0644 -// NginxController updates NGINX configuration, starts and reloads NGINX -type NginxController struct { +// Controller updates NGINX configuration, starts and reloads NGINX +type Controller struct { nginxConfdPath string nginxSecretsPath string local bool @@ -137,8 +137,8 @@ type Location struct { IngressResource string } -// NginxMainConfig describe the main NGINX configuration file -type NginxMainConfig struct { +// MainConfig describe the main NGINX configuration file +type MainConfig struct { ServerNamesHashBucketSize string ServerNamesHashMaxSize string LogFormat string @@ -182,8 +182,8 @@ func NewUpstreamWithDefaultServer(name string) Upstream { } // NewNginxController creates a NGINX controller -func NewNginxController(nginxConfPath string, local bool) *NginxController { - ngxc := NginxController{ +func NewNginxController(nginxConfPath string, local bool) *Controller { + ngxc := Controller{ nginxConfdPath: path.Join(nginxConfPath, "conf.d"), nginxSecretsPath: path.Join(nginxConfPath, "secrets"), local: local, @@ -194,7 +194,7 @@ func NewNginxController(nginxConfPath string, local bool) *NginxController { // DeleteIngress deletes the configuration file, which corresponds for the // specified ingress from NGINX conf directory -func (nginx *NginxController) DeleteIngress(name string) { +func (nginx *Controller) DeleteIngress(name string) { filename := nginx.getIngressNginxConfigFileName(name) glog.V(3).Infof("deleting %v", filename) @@ -206,7 +206,7 @@ func (nginx *NginxController) DeleteIngress(name string) { } // AddOrUpdateDHParam creates the servers dhparam.pem file -func (nginx *NginxController) AddOrUpdateDHParam(dhparam string) (string, error) { +func (nginx *Controller) AddOrUpdateDHParam(dhparam string) (string, error) { fileName := nginx.nginxSecretsPath + "/" + dhparamFilename if !nginx.local { pem, err := os.Create(fileName) @@ -224,7 +224,7 @@ func (nginx *NginxController) AddOrUpdateDHParam(dhparam string) (string, error) } // AddOrUpdateSecretFile creates a file with the specified name, content and mode. -func (nginx *NginxController) AddOrUpdateSecretFile(name string, content []byte, mode os.FileMode) string { +func (nginx *Controller) AddOrUpdateSecretFile(name string, content []byte, mode os.FileMode) string { filename := nginx.getSecretFileName(name) if !nginx.local { @@ -258,7 +258,7 @@ func (nginx *NginxController) AddOrUpdateSecretFile(name string, content []byte, } // DeleteSecretFile the file with a Secret -func (nginx *NginxController) DeleteSecretFile(name string) { +func (nginx *Controller) DeleteSecretFile(name string) { filename := nginx.getSecretFileName(name) glog.V(3).Infof("deleting %v", filename) @@ -270,16 +270,16 @@ func (nginx *NginxController) DeleteSecretFile(name string) { } -func (nginx *NginxController) getIngressNginxConfigFileName(name string) string { +func (nginx *Controller) getIngressNginxConfigFileName(name string) string { return path.Join(nginx.nginxConfdPath, name+".conf") } -func (nginx *NginxController) getSecretFileName(name string) string { +func (nginx *Controller) getSecretFileName(name string) string { return path.Join(nginx.nginxSecretsPath, name) } // Reload reloads NGINX -func (nginx *NginxController) Reload() error { +func (nginx *Controller) Reload() error { if !nginx.local { if err := shellOut("nginx -t"); err != nil { return fmt.Errorf("Invalid nginx configuration detected, not reloading: %s", err) @@ -294,7 +294,7 @@ func (nginx *NginxController) Reload() error { } // Start starts NGINX -func (nginx *NginxController) Start(done chan error) { +func (nginx *Controller) Start(done chan error) { if !nginx.local { cmd := exec.Command("nginx") cmd.Stdout = os.Stdout @@ -311,7 +311,7 @@ func (nginx *NginxController) Start(done chan error) { } // Quit shutdowns NGINX gracefully -func (nginx *NginxController) Quit() { +func (nginx *Controller) Quit() { if !nginx.local { if err := shellOut("nginx -s quit"); err != nil { glog.Fatalf("Failed to quit nginx: %v", err) @@ -351,7 +351,7 @@ func shellOut(cmd string) (err error) { } // UpdateMainConfigFile writes the main NGINX configuration file to the filesystem -func (nginx *NginxController) UpdateMainConfigFile(cfg []byte) { +func (nginx *Controller) UpdateMainConfigFile(cfg []byte) { filename := "/etc/nginx/nginx.conf" glog.V(3).Infof("Writing NGINX conf to %v", filename) @@ -374,7 +374,7 @@ func (nginx *NginxController) UpdateMainConfigFile(cfg []byte) { } // UpdateIngressConfigFile writes the Ingress configuration file to the filesystem -func (nginx *NginxController) UpdateIngressConfigFile(name string, cfg []byte) { +func (nginx *Controller) UpdateIngressConfigFile(name string, cfg []byte) { filename := nginx.getIngressNginxConfigFileName(name) glog.V(3).Infof("Writing Ingress conf to %v", filename) diff --git a/internal/nginx/plus/nginx_api.go b/internal/nginx/plus/nginx_api.go index a887e5e7e8..69c7d7119d 100644 --- a/internal/nginx/plus/nginx_api.go +++ b/internal/nginx/plus/nginx_api.go @@ -6,17 +6,20 @@ import ( "github.com/golang/glog" ) +// NginxAPIController works with the NGINX API type NginxAPIController struct { client *NginxClient local bool } +// ServerConfig holds the config data type ServerConfig struct { MaxFails int64 FailTimeout string SlowStart string } +// NewNginxAPIController creates an instance of NginxAPIController func NewNginxAPIController(httpClient *http.Client, endpoint string, local bool) (*NginxAPIController, error) { client, err := NewNginxClient(httpClient, endpoint) if !local && err != nil { @@ -26,6 +29,7 @@ func NewNginxAPIController(httpClient *http.Client, endpoint string, local bool) return nginx, nil } +// UpdateServers updates upstream servers func (nginx *NginxAPIController) UpdateServers(upstream string, servers []string, config ServerConfig) error { if nginx.local { glog.V(3).Infof("Updating endpoints of %v: %v\n", upstream, servers) diff --git a/internal/nginx/plus/nginx_client.go b/internal/nginx/plus/nginx_client.go index bde2a0fb5d..d902d8eaa5 100644 --- a/internal/nginx/plus/nginx_client.go +++ b/internal/nginx/plus/nginx_client.go @@ -20,6 +20,7 @@ type NginxClient struct { type versions []int +// UpstreamServer holds the fields for an upstream server type UpstreamServer struct { ID int64 `json:"id,omitempty"` Server string `json:"server"` diff --git a/internal/nginx/template_executor.go b/internal/nginx/template_executor.go index 66055c2d32..306f5a05a1 100644 --- a/internal/nginx/template_executor.go +++ b/internal/nginx/template_executor.go @@ -60,7 +60,7 @@ func (te *TemplateExecutor) UpdateIngressTemplate(templateString *string) error } // ExecuteMainConfigTemplate generates the content of the main NGINX configuration file -func (te *TemplateExecutor) ExecuteMainConfigTemplate(cfg *NginxMainConfig) ([]byte, error) { +func (te *TemplateExecutor) ExecuteMainConfigTemplate(cfg *MainConfig) ([]byte, error) { cfg.HealthStatus = te.HealthStatus cfg.NginxStatus = te.NginxStatus cfg.NginxStatusPort = te.NginxStatusPort diff --git a/internal/nginx/templates/templates_test.go b/internal/nginx/templates/templates_test.go index db02b9faad..221b64040f 100644 --- a/internal/nginx/templates/templates_test.go +++ b/internal/nginx/templates/templates_test.go @@ -80,7 +80,7 @@ var ingCfg = nginx.IngressNginxConfig{ Keepalive: "16", } -var mainCfg = nginx.NginxMainConfig{ +var mainCfg = nginx.MainConfig{ ServerNamesHashMaxSize: "512", ServerTokens: "off", WorkerProcesses: "auto", diff --git a/internal/queue/queue.go b/internal/queue/queue.go index 68f08ea461..d7013a5ff8 100644 --- a/internal/queue/queue.go +++ b/internal/queue/queue.go @@ -32,6 +32,7 @@ func NewTaskQueue(syncFn func(Task)) *TaskQueue { } } +// Run begins running the worker for the given duration func (t *TaskQueue) Run(period time.Duration, stopCh <-chan struct{}) { wait.Until(t.worker, period, stopCh) } @@ -55,11 +56,13 @@ func (t *TaskQueue) Enqueue(obj interface{}) { t.queue.Add(task) } +// Requeue adds the task to the queue again and logs the given error func (t *TaskQueue) Requeue(task Task, err error) { glog.Errorf("Requeuing %v, err %v", task.Key, err) t.queue.Add(task) } +// RequeueAfter adds the task to the queue after the given duration func (t *TaskQueue) RequeueAfter(task Task, err error, after time.Duration) { glog.Errorf("Requeuing %v after %s, err %v", task.Key, after.String(), err) go func(task Task, after time.Duration) { @@ -68,7 +71,7 @@ func (t *TaskQueue) RequeueAfter(task Task, err error, after time.Duration) { }(task, after) } -// worker processes work in the queue through sync. +// Worker processes work in the queue through sync. func (t *TaskQueue) worker() { for { task, quit := t.queue.Get() @@ -82,7 +85,7 @@ func (t *TaskQueue) worker() { } } -// shutdown shuts down the work queue and waits for the worker to ACK +// Shutdown shuts down the work queue and waits for the worker to ACK func (t *TaskQueue) Shutdown() { t.queue.ShutDown() <-t.workerDone diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 6c3965382d..a85eb23b1d 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -147,6 +147,7 @@ type StoreToSecretLister struct { cache.Store } +// IsMinion determines is an ingress is a minion or not func IsMinion(ing *extensions.Ingress) bool { if ing.Annotations["nginx.org/mergeable-ingress-type"] == "minion" { return true @@ -154,6 +155,7 @@ func IsMinion(ing *extensions.Ingress) bool { return false } +// IsMaster determines is an ingress is a master or not func IsMaster(ing *extensions.Ingress) bool { if ing.Annotations["nginx.org/mergeable-ingress-type"] == "master" { return true @@ -161,6 +163,7 @@ func IsMaster(ing *extensions.Ingress) bool { return false } +// HasChanges determines if current ingress has changes compared to old ingress func HasChanges(old *extensions.Ingress, current *extensions.Ingress) bool { old.Status.LoadBalancer.Ingress = current.Status.LoadBalancer.Ingress old.ResourceVersion = current.ResourceVersion From 82a75dac6e9db126485183c3686221c30a1a474f Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Thu, 6 Sep 2018 16:05:53 +0100 Subject: [PATCH 09/10] Use Dockerfile as copy target --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 65225cb526..ad12192e91 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ DOCKER_RUN = docker run --rm -v $(shell pwd):/go/src/github.com/nginxinc/kuberne DOCKER_BUILD_RUN = docker run --rm -v $(shell pwd):/go/src/github.com/nginxinc/kubernetes-ingress -w /go/src/github.com/nginxinc/kubernetes-ingress/cmd/nginx-ingress/ GOLANG_CONTAINER = golang:1.10 DOCKERFILEPATH = build -DOCKERFILE = Dockerfile +DOCKERFILE = Dockerfile # note, this can be overwritten e.g. can be DOCKERFILE=DockerFileForPlus BUILD_IN_CONTAINER = 1 PUSH_TO_GCR = @@ -37,8 +37,8 @@ ifeq ($(GENERATE_DEFAULT_CERT_AND_KEY),1) endif container: test nginx-ingress certificate-and-key - cp $(DOCKERFILEPATH)/$(DOCKERFILE) . - docker build $(DOCKER_BUILD_OPTIONS) -f $(DOCKERFILE) -t $(PREFIX):$(TAG) . + cp $(DOCKERFILEPATH)/$(DOCKERFILE) ./Dockerfile + docker build $(DOCKER_BUILD_OPTIONS) -f Dockerfile -t $(PREFIX):$(TAG) . push: container ifeq ($(PUSH_TO_GCR),1) @@ -49,4 +49,4 @@ endif clean: rm -f nginx-ingress - rm $(DOCKERFILE) + rm Dockerfile From 2f3931046773ffa75bdba024d7d4e5faf4f55a46 Mon Sep 17 00:00:00 2001 From: Peter Kelly Date: Thu, 6 Sep 2018 16:20:39 +0100 Subject: [PATCH 10/10] Use -f sp make clean will not error if file not present --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ad12192e91..3ddcf2abda 100644 --- a/Makefile +++ b/Makefile @@ -49,4 +49,4 @@ endif clean: rm -f nginx-ingress - rm Dockerfile + rm -f Dockerfile